Wednesday, May 20, 2015

Getting started with CXM - The User Journey Purchase Loop

No one is like the other 
In Sweden four large new pharmacies was founded exactly the same day. The first of July 2009 was the first day when deregulated non-government owned pharmacies was allowed in the country.

None of the new pharmacies had any time consuming legacy that day. No existing marketing plans, no previous IT-systems setup, specific digital marketing consultancies contracted nor any other general policies guides up and running.

Not even those four companies, founded at the exact same moment, should try to copy each other’s customer experience strategy.

Even if two competitors are in the same business, have the same clients, goals and means – successful customer experience management has turned out to be something absolutely unique.

 The management of a customer experience is much more than a market and a product. It boils down to one company’s:

• General marketing ambitions
• Basic knowledge of analysis
• Will to quickly adapt and..
 • Type of contracted and employed staff as well as hierarchies

However there are some aids to help you get started. Nansen will go through some of them here!

User Journey Purchase Loop
The definition of the customer journey has long been looked upon as a good start for Customer Experience strategy definition. One of the second best templates to originate from is the User Journey Purchase Loop.

A great and modern look into how the purchase process and the decision making steps within a buy rolls out. The sum of all interactions with a customer. Answers when the customers will feel and ask questions like "Be transparent", "Reward me", "Make it easy", Earn my trust" and so on.

A broad definition, open for each CXM-interested company to adapt and make their own. And once completed possible to plan for, target analytics and KPI:s towards as well as marketing automation. Therefor really useful. Take a look!


Tuesday, May 12, 2015

Localize Property Name Based on Content Language

We recently had a client request that a page property have a different display name for each language branch.  The function of the property was as an identifier and would always be used the same in the back end but the editors in each country had a different name for the property.

This isn't a particularly inspired solution, but I'm hoping to save someone else the time it took to stumble upon this.

It is possible to localize EPi property names using the built in Display attribute and keeping the translations in resources files (see this stackoverflow post here), but this is only based on the UI language in Edit/Admin mode and not on content language.

I created an EditorDescriptor that will take the string entered in the Name field and try to translate it using the registered LocalizationService (whatever that may be).  An important thing to note is the EditorDescriptorBehavior.  We have to have it as EditorDescriptorBehavior.PlaceLast to ensure that any other logic to get the Display Name (built in translation, etc) does not interfere with what we want displayed.

Code


[EditorDescriptorRegistration(TargetType = typeof(String), UIHint = SiteUIHints.LocalizedDisplay, EditorDescriptorBehavior = EditorDescriptorBehavior.PlaceLast)]
public class LocalizableDisplayEditorDescriptor : EditorDescriptor
{
   public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
   {
      base.ModifyMetadata(metadata, attributes);

      Attribute attr = attributes.FirstOrDefault(a => a.GetType() == typeof(DisplayAttribute));
      if (attr != null)
      {
         string translated =                                     

             ServiceLocator.Current.GetInstance<LocalizationService().GetStringByCulture(metadata.DisplayName, 
             FallbackBehaviors.None, ContentLanguage.PreferredCulture);

         if (!string.IsNullOrWhiteSpace(translated))
            metadata.DisplayName = translated;
      }
   }
}



Usage

[UIHint(SiteUIHints.LocalizedDisplay)]
[Display(Name = "/properties/InternalId/displayname", Order = 200)]
public virtual string InternalId { get; set; }