Blog

No dead ends – what to include on your Sitecore form “Thank you” page

Key points:

  • It is rare for a Sitecore website not to have some kind of form
  • Something that is often overlooked – the “Thank You” / on submit page
  • This page is a great opportunity to add goals, links to next best actions and can be personalised
  • You can also use A/B testing to see which get best results
  • By optimising this page you give yourself the best chance to keep the visitor engaged and on your website

In around a decade of working on websites, in particular Sitecore sites, I would estimate that 99% of those websites contain at least one form for a visitor to complete.

One thing often overlooked is what happens once the form is submitted? Usually data from the form is saved and/or emailed, and the user is taken to a “Thank You” page, or a pop-up overlay may appear as a result.

In the majority of cases the content that appears on this page isn’t well thought through. How many times have you seen a message that simply says “Thanks, we’ll get back to you.” And that’s it – where does the website visitor go now?

This is a significantly lost opportunity – and potentially a costly one. The thank you/on submit page is an opportunity to keep your visitor’s attention and direct them to the next best action you want them to take.

At a minimum a Sitecore goal should be triggered that allocates Engagement Value Scale points to the activity.

Links to further relevant content should also be included. Depending on the digital maturity of the organisation these should also be personalised as much as possible. Think of the leading ecommerce retailers – they will show you a range of products recommended based on your purchase history.

It is also an opportunity to use A/B and multivariate testing to see which messages and calls to action generate the best results. These in turn can generate higher engagement levels and drive business outcomes.

In summary – the longer you can keep a visitor on your site, the greater return you will get on your Sitecore investment. The humble form “Thank You” page is an opportunity that should not be overlooked.

For more information about Aceik’s Sitecore Optimisation Packages, please contact us at sitecoreoptimisation@aceik.com.au

Photo by Nick Fewings on Unsplash

Aceik & Sitecore’s Whisky Tasting & CX Roundtable

Last week, Aceik and Sitecore brought together 18 digital experts from around Australia to discuss customer experience – the trends, challenges and risks facing a new project in 2021. And it wouldn’t be a robust discussion without a little whisky tasting – kindly delivered by Melbourne’s The Elysian Whisky Bar.

Our moderator introduced two topics then guests were divided into groups of 6 to discuss. Upon return to the main track, guests then shared their unique discussion. And today, we wanted to share the key highlights.

Question 1

Thinking of your ultimate goal for your customer experience: Where does personalisation and marketing automation fit in, and what has been the most significant step you’ve taken towards that goal in the last 12 months?

  • Need to answer the question – what is the goal of website? why do we have a website? Many competing internal stakeholders (e.g. buyers v sellers)
  • xConnect implementation issues – holding back use of marketing features
  • Constrained internally (resources, budget)
  • Lots and lots of content – how to deliver the right content to the right people
  • Targeting an audience to help them through a specific journey
  • A lot of marketing automation – Facebook and Google advertising – open rates response rates – deliverability of email – personalised to get better open rate – lots of experimentation – gain more information – and helping them through the marketing funnel
  • Xdb – issues – business priorities – can’t start the journey.
  • Quick wins – show/prove value

Question 2

Thinking of that ideal CX, what steps will you take for the next 12 months?

  • Quick wins are the focus all round – esp. marketing
  • Maintainability – JSS, SXA
  • Content, content, content – and how to manage
  • How to upsell better online – parts, service; portal for owners – service history, finance offers.
  • Ease of access to information, engagement on the website, simple discoverable info
  • Learn more about the primary personas/segments
  • Alignment of brand and service
  • More content for SEO and drive more traffic to website
  • Automate the creation of pages with data have
  • Cost effective ways of producing rich content
  • Complete digital sign up
  • Transform the experience in engaging with the brand for the first time
  • Brand awareness, show expertise, show thought leadership
  • Pattern matching to industries
  • CRM integration

It was a fantastic event and we really appreciate the open sharing amongst the group!

People of Aceik: Lila Tournier, Delivery and Operations Manager

Continuing on with our People of Aceik series, where we introduce you to our talented team mates, this month, we sat down with our Delivery and Operations Manager, Lila Tournier (note – it’s pronounced Lee-la, like from Futurama).

If you missed the last one with Praveen Manchana, you can catch up here.

Lila, tell us a bit about yourself

Lila: In terms of my career background, I started in advertising agencies, working through the line – so anything from TV, press and radio ads, brochures, point of sales, emails, online advertising… anything! 

I then moved internally to a digital focus role as it felt that this was the future and I loved the fact that there is always something to learn. 

From big ad land agencies in Sydney, I moved to Melbourne to digital agencies, from small to large consulting ones, and I’m now here at Aceik.

Tell us about why you decided to join Aceik

Lila: It happened rather randomly actually. Tim O’Neill, the former CEO of Reactive and current friend of Aceik put me onto the job. In the same week that Tim got in touch, I heard from 2 ex-colleagues that they were joining Aceik and I thought hang on, there is something to explore here. 

I wasn’t looking for a role, but Aceik seemed so attractive in terms of where it was at: a small agency with a blank canvas to work with and the opportunity to help shape and grow the business. Being part of that growth journey was something that was so exciting, so it was a quick and easy decision. 

What are you working on at the moment?

Lila: I’m lucky to work on a mixture of projects – there are just too many to explain! But it keeps the days diverse.

Tell us about yourself outside of Aceik hours

Lila: Outside of work, I’m also a farmer 🙂 I know that sounds weird but we have a small farm, mainly managing sheep but do also have a few rescues, so a bit like Noah’s Ark. 

This makes things very interesting and very busy when also coupled with our two young children! 

If someone wants to follow a career in your steps, what would you recommend?

Lila: Try anything and learn as much as you can early on. 

Content strategy is essential to maximise Sitecore’s potential

Key points:

  • Most digital marketing features (personalisation, A/B testing, marketing automation) require multiple different sets of content to be effective
  • It is essential to have a content marketing plan
  • Start small – think about resources required, brainstorm for quick wins
  • Test and learn
  • Focus on high value, low implementation effort
  • Regardless of personalisation, a content calendar is essential to drive traffic to your website
  • The content calendar should include the type of content, which channel it will be posted to (e.g. website, Facebook, Instagram, LinkedIn, Twitter), bearing in mind the target audience

It is a worn-out cliché, but “Content is King” still resonates when it comes to digital marketing.

Whilst the phrase may be true, there is another that is equally as important: your content strategy is a critical advisor to the King.

You may have the greatest content in your field, but without a realistic content and distribution schedule, that content may never reach your audience.

Start small – creating good content requires a serious amount of thought and effort.

Test and learn. Don’t be afraid to fail.

A content calendar is critically important to the success of your content strategy. It must include the type of content (written, image, video etc), which channel it will be posted to (website, Facebook, Instagram, LinkedIn, Twitter etc), bearing in mind the target audience.

Ideally a yearly content plan can be developed, but for some organisations this may be unrealistic, and a shorter timeframe required.

Your content should be a combination of content that can be used at any time, and reactionary content that is time-critical. You need to have content created in advance to use across the calendar, but you also need to be able to react to changes in circumstances.

If there is a major announcement in your industry then you must be able to generate content and get it live as quickly as possible.

I was lucky enough to be heading up the Richmond Football Club’s digital team in 2017 when the club won their first AFL premiership in 37 years. An impromptu performance by Richmond star Jack Riewoldt with The Killers to sing Mr Brightside generated millions of video views, and led to a string of content that will remain amongst the most engaging, highest reach content the club produces. The outcome? A massive increase in followers on all social channels, growing the known audience that the club can engage and transact with in future

A word of warning – high levels of personalisation will require a large volume of content. This must be taken into account with your internal and/or external resourcing.

Ultimately the best digital content strategy will take into account the effort it takes to produce content to generate a positive ROI. By following the above recommendations you will have a head start on your content marketing journey.

For more information about Aceik’s Sitecore Optimisation Packages, please contact us at sitecoreoptimisation@aceik.com.au

Photo by Jason Goodman on Unsplash

Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 4

In Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 1, I showed you how you can import contacts from a CSV file into a list in Sitecore. In Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 2, I showed you how you can add to the list of out of the box supported fields when importing contacts into Sitecore. In Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 3, I showed you how you can create your own custom facets and populate them for your contacts as you import them. If you haven’t already read them, head over and read them first.

In Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 4, I’m now going to demonstrate how you can update the Experience Profile for a Contact by Add a new Tab into the User Interface and displaying your Custom Facet information.

Experience Profile Express Tab

Instead of developing all of this code from scratch, we’re going to use a package available in NuGet specifically written for this purpose. No point reinventing the wheel when someone else has already done all the hard work for you.

Experience Profile Express Tab is a package developed to streamline the creation of new tabs in the Experience Profile.

The first step we’ll take is to add the EPExpressTab to our project using NuGet. This will install two packages. EPExpressTab.Core and EXExpressTab. At the time of writing, version 2.0.2 was the latest released version.

To use EP Express Tab, we need to do the following:

  • Create a custom ViewModel that will represent the custom data we wish to display in the Experience Profile Tab
  • Create a custom EPExpressViewModel that will act as a Controller of sorts that will be called by EPExpressTab to populate our custom View Model and pass it to our view
  • Create a View to render the content for out custom tab in Experience Profile

First, let’s create our custom view model. In this example, this will contain just the new Employee fields the same as out custom Facet. Nothing special here. It’s just a standard class to hold our view model.

using System;

namespace Aceik.Feature.EXM.Models
{
    public class EmployeeViewModel
    {
        public string EmployeeId { get; set; }
        public string Department { get; set; }
        public DateTime? StartDate { get; set; }
        public string EmployeeType { get; set; }
    }
}

Next we need to create our EPExpressTab “Controller” class. This class is called by EPExpressTab and is used to generate the instance of our view model and pass it to the view.

using EPExpressTab.Data;
using EPExpressTab.Repositories;
using System;

namespace Aceik.Feature.EXM.Models
{
    public class EPCustomModel : EpExpressViewModel
    {
        public override string TabLabel => "Employee";
        public override string Heading => "Employee Details";

        public override object GetModel(Guid contactId)
        {
            Sitecore.XConnect.Contact model = EPRepository.GetContact(contactId, new string[] { EmployeeInfo.DefaultFacetKey });

            var employeeInfo = model.GetFacet<EmployeeInfo>();

            return new EmployeeViewModel
            {
                EmployeeId = employeeInfo?.EmployeeId,
                Department = employeeInfo?.Department,
                StartDate = employeeInfo?.StartDate,
                EmployeeType = employeeInfo?.EmployeeType
            };
        }

        public override string GetFullViewPath(object model)
        {
            return "/views/Aceik/Feature/EXM/Employee.cshtml";
        }
    }
}

The GetModel method is the action that is called to create the view model instance that will be passed to the view.

The GetFullViewPath method is as described. The method to get the path to the view.

The view itself it pretty straight forward with some inline styles defined, and the html tags etc to render the required custom data.

@model Aceik.Feature.EXM.Models.EmployeeViewModel
<style>
    .employee-border {
        padding-top: 10px !important;
        float: left;
        width: 100%;
    }

    .employee-text {
        display: block;
        float: left;
        width: 150px;
        color: #707070;
        clear: both;
    }

    .employee-value {
        clear: unset;
        padding-left: 95px;
        width: calc(100% - 150px);
        color: #121212;
    }
</style>
<div class="row">
    <div class="col-md-6">
        <span class="sc-text sc-text-value">Employee</span>
        <div class="sc-border employee-border">
            <span class="sc-text employee-text">Employee Id</span>
            <span class="sc-text employee-text employee-value">@Model.EmployeeId</span>
        </div>
        <div class="sc-border employee-border">
            <span class="sc-text employee-text">Department</span>
            <span class="sc-text employee-text employee-value">@Model.Department</span>
        </div>
        <div class="sc-border employee-border">
            <span class="sc-text employee-text">Start Date</span>
            <span class="sc-text employee-text employee-value">
                @if (Model.StartDate.HasValue)
                {
                    @Model.StartDate.Value.ToLocalTime().ToString("dd/MM/yyyy")
                }
            </span>
        </div>
        <div class="sc-border employee-border">
            <span class="sc-text employee-text">Employee Type</span>
            <span class="sc-text employee-text employee-value">@Model.EmployeeType</span>
        </div>
    </div>
</div>

Once this is deployed, along with the added EpExpressTab.config file that is added to the project with the inclusion of the NuGet package, you can now view the “Employee” tab in the Experience Profile that now shows the custom EmployeeInfo Facet data.

So you can examine the solution for yourself, please see below a link to the zip file containing the full Visual Studio solution, CSV files and a Sitecore package for the Import Map configuration items.

AceikEXM.zip

Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 3

In Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 1, I showed you how you can import contacts from a CSV file into a list in Sitecore. In Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 2, I demonstrated how you can add to the list of out of the box supported fields when importing contacts into Sitecore. If you haven’t read these as yet, best to start with them first.

In Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 3, I’m going to share with you how you can create your own custom facets and populate them for your contacts as you import them.

To do this, you are going to need to complete the following tasks:

  • Create a custom facet that will describe the additional data you wish to store for your contacts
  • Build a model for your custom facet that will be used by Xdb to store your custom facet data
  • Serialize your custom model and publish it so that Xdb will recognise your model
  • Create a custom Import mapper class that will be used by the Import process to read your custom fields from the import data and write it to your custom facet
  • Update the Import map configuration so that you can map the fields of your CSV file on import
  • Create the required Sitecore configuration settings for your facet and facet import mapper
  • Deploy the updated/new files to Sitecore and XConnect

Create a custom facet

We are going to store Employee information for each of our contacts. To support that, the first thing we are going to need to do is to create our own custom Facet.

Using Sitecore Helix principles and guidelines, I’ve created a new Feature project in Visual Studio that will contain all the custom code to support our custom EXM requirements. In this project, I’ve started with adding a new Facet class called EmployeeInfo:

using System;
using Sitecore.XConnect;

namespace Aceik.Feature.EXM.Models
{
    public class EmployeeInfo : Facet
    {
        public const string DefaultFacetKey = "EmployeeInfo";
        public string EmployeeId { get; set; }
        public string Department { get; set; }
        public DateTime? StartDate { get; set; }
        public string EmployeeType { get; set; }
    }
}

My EmployeeInfo facet, contains 4 properties that I want to be able to populate for my contacts:

  • EmployeeId
  • Department
  • StartDate
  • EmployeeType

Build a model for your custom Facet

The next thing I need to do is to create an XdbModel for my custom Facet. This is required to be deployed into our XConnect instance and will allow XConnect to know about our custom Facet and be able to store the Facet details for each contact.

using Sitecore.XConnect;
using Sitecore.XConnect.Schema;

namespace Aceik.Feature.EXM.Models
{
    public class EmployeeModel
    {
        public static XdbModel Model { get; } = EmployeeModel.BuildModel();

        private static XdbModel BuildModel()
        {
            XdbModelBuilder modelBuilder = new XdbModelBuilder("EmployeeModel", new XdbModelVersion(1, 0));

            modelBuilder.ReferenceModel(Sitecore.XConnect.Collection.Model.CollectionModel.Model);
            modelBuilder.DefineFacet<Contact, EmployeeInfo>(EmployeeInfo.DefaultFacetKey);

            return modelBuilder.BuildModel();
        }
    }
}

Note: Pay attention to the XdbModelBuilder parameters. This instructs the model with our custom Facet details.

We now need to run a build on our new project in Visual Studio so that the assembly can be generated with our classes.

Serlialize your custom model

XConnect requires a JSON representation of your XdbModel. We will now create a console application that can be used to generated the required JSON file.

First, Add a new project to your solution in Visual Studio, selecting to use the Console App template.

You will need to add a reference to your Feature project into the Console application as well as Nuget reference to the Sitecore.XConnect package.

Update the program.cs file to look like below:

using Sitecore.XConnect.Serialization;
using System.IO;

namespace Aceik.Feature.EXM.Serialize
{
    class Program
    {
        static void Main(string[] args)
        {
            // File name will be "Aceik.Feature.Mail.Models.EmployeeModel, 1.0.json
            var json = XdbModelWriter.Serialize(Models.EmployeeModel.Model);
            File.WriteAllText("Aceik.Feature.EXM.Models." + Models.EmployeeModel.Model.FullName + ".json", json);
        }
    }
}

Build and execute the console application.

As per the code comments, this will generate a file called “Aceik.Feature.Mail.Models.EmployeeModel, 1.0.json”. This will vary based on your custom model name and versioning you assigned in your XdbModel.

Note: If after deploying your model to XConnect, you need to update it, you will need to update the XdbModel version and deploy the updated JSON file before XConnect will recognise the new properties of your custom facet.

Create a custom import mapper

When a contact is imported via CSV, various ImportMapper classes are executed to process the contact and to populate the various Facets with the data from the CSV.

To populate our custom Facet, we need to create our own custom ImportMapper class to do this.

To process the contacts employee fields, I created my custom import mapper class called EmployeeInfoFacetMapper.

using System;
using System.Globalization;
using Sitecore.Diagnostics;
using Sitecore.ListManagement.Import;
using Sitecore.ListManagement.XConnect.Web.Import;
using Sitecore.XConnect;
using Aceik.Feature.EXM.Models;

namespace Aceik.Feature.EXM.Import
{
    public class EmployeeInfoFacetMapper : IFacetMapper
    {
        public EmployeeInfoFacetMapper() : this(EmployeeInfo.DefaultFacetKey)
        {
        }

        public EmployeeInfoFacetMapper(string facetName)
        {
            Assert.ArgumentNotNull(facetName, nameof(facetName));
            this.FacetName = facetName;
        }

        public string FacetName { get; }

        public MappingResult Map(
          string facetKey,
          Facet source,
          ContactMappingInfo mappings,
          string[] data)
        {
            if (facetKey != this.FacetName)
                return new NoMatch(facetKey);

            var facet = source as EmployeeInfo ?? new EmployeeInfo();

            // EmployeeInfo Properties
            facet.EmployeeId = SetTextField(FacetName, mappings, data, "EmployeeId");
            facet.Department = SetTextField(FacetName, mappings, data, "Department");
            facet.StartDate = SetDateTimeField(FacetName, mappings, data, "StartDate", "dd/MM/yyyy");
            facet.EmployeeType = SetTextField(FacetName, mappings, data, "EmployeeType");

            return new FacetMapped(facetKey, facet);
        }

        private string SetTextField(string facetName, ContactMappingInfo mappings, string[] data, string fieldName) => mappings.GetValue($"{facetName}_{fieldName}", data);

        private DateTime? SetDateTimeField(string facetName, ContactMappingInfo mappings, string[] data, string fieldName, string dateFormat)
        {
            DateTime? fieldValue = null;
            var fieldText = mappings.GetValue($"{facetName}_{fieldName}", data);
            DateTime fieldDate;

            if (DateTime.TryParseExact(fieldText, dateFormat, new CultureInfo("en-AU"), DateTimeStyles.None, out fieldDate))
                fieldValue = fieldDate.ToUniversalTime();

            return fieldValue;
        }
    }
}

This class is instantiated for each contact. First, it verifies that the data being passed to it is for the EmployeeInfo facet. Once that is confirmed, it populates the EmployeeInfo facet properties from the CSV data that is passed into it.

As you can see, I’ve used a couple of private methods to extract and set the string and DateTime values passed in.

Notice that when extracting the values from the mappings data passed in, it uses a pattern to extract the data for the correct field: “{facetName}_{fieldName}”. This pattern matches the Import mappings that we will setup in the next step.

Import Mapping Fields

As per Part 2, we need to configure the custom Import Mapping fields. Once again, switch to the Core database in Sitecore and navigate to this path: “/sitecore/client/Applications/List Manager/Dialogs/ImportWizardDialog/PageSettings/TabControl Parameters/Map/ImportModel”.

Select one of the existing mapping fields and duplicate it giving it a name of “Employee Info – Employee Id”. Populate the FieldName and DataField fields as per below. Note that the DataField value is the value used in the Import Mapper classes to identify the field so these need to be carefully assigned to match your custom Import Mapper class.

Do the same 3 more times to create the custom import mapping fields for:

  • Employee Info – Department
  • Employee Info – Start Date
  • Employee Info – Employee Type

Create the Sitecore configuration

In your project, you will need to create configuration files for the following purposes:

  • Patch the ListManagement.Import.FacetsToMap setting so that it includes your custom Facet name
  • Add your custom FacetMapper to the list of Import Facet Mappers defined in Sitecore
  • Add your schema to the list of schemas defined for XConnect
  • Add your projects path to the Layer configuration so that your configuration files are recognized

In my EXM Helix project, I’ve added the following configuration files:

  • ListManagement.config
  • sc.Aceik.Feature.EXM.Models.EmployeeModel.xml
  • Layers.config
ListManagement.config
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
  <sitecore>
    <settings>
      <setting name="ListManagement.Import.FacetsToMap" set:value="Emails|Personal|Addresses|EmployeeInfo" />
    </settings>

    <import>
      <facetMapper type="Sitecore.ListManagement.XConnect.Web.Import.CompositeFacetMapperCollection, Sitecore.ListManagement.XConnect.Web">
        <param resolve="true" type="Sitecore.Abstractions.BaseLog, Sitecore.Kernel"/>
        <facetMappers hint="list:Add">
          <facetMapper type="Aceik.Feature.EXM.Import.EmployeeInfoFacetMapper, Aceik.Feature.EXM" />
        </facetMappers>
      </facetMapper>
    </import>

    <xconnect>
      <runtime type="Sitecore.XConnect.Client.Configuration.RuntimeModelConfiguration,Sitecore.XConnect.Client.Configuration">
        <schemas hint="list:AddModelConfiguration">
          <!-- value of 'name' property must be unique -->
          <schema name="employeemodel" type="Sitecore.XConnect.Client.Configuration.StaticModelConfiguration,Sitecore.XConnect.Client.Configuration" patch:after="schema[@name='collectionmodel']">
            <param desc="modeltype">Aceik.Feature.EXM.Models.EmployeeModel, Aceik.Feature.EXM</param>
          </schema>
        </schemas>
      </runtime>
    </xconnect>

  </sitecore>
</configuration>
sc.Aceik.Feature.EXM.Models.EmployeeModel.xml
<?xml version="1.0" encoding="utf-8"?>
<Settings>
  <Sitecore>
    <XConnect>
      <Services>
        <XConnect.Client.Configuration>
          <Options>
            <Models>
              <EmployeeModel>
                <TypeName>Aceik.Feature.EXM.Models.EmployeeModel, Aceik.Feature.EXM</TypeName>
                <PropertyName>Model</PropertyName>
              </EmployeeModel>
            </Models>
          </Options>
        </XConnect.Client.Configuration>
      </Services>
    </XConnect>
  </Sitecore>
</Settings>
Layers.config
<?xml version="1.0" encoding="utf-8"?>
<layers>
  <layer name="Sitecore" includeFolder="/App_Config/Sitecore/">
    <loadOrder>
      <add path="ContentSearch.Azure" type="Folder" />
      <add path="Reporting" type="Folder" />
      <add path="Marketing.Xdb.Sql.Common" type="Folder" />
      <add path="CMS.Core" type="Folder" />
      <add path="AntiCSRFModule" type="Folder" />
      <add path="Contact.Enrichment.Services.Client" type="Folder" />
      <add path="ContentSearch" type="Folder" />
      <add path="Buckets" type="Folder" />
      <add path="DeviceDetection.Client" type="Folder" />
      <add path="DetectionServices.Location" type="Folder" />
      <add path="ItemWebApi" type="Folder" />
      <add path="Owin.Authentication" type="Folder" />
      <add path="Owin.Authentication.IdentityServer" type="Folder" />
      <add path="TransientFaultHandling" type="Folder" />
      <add path="Messaging" type="Folder" />
      <add path="Processing.Tasks.Messaging.Xmgmt" type="Folder" />
      <add path="Update" type="Folder" />
      <add path="XConnect.Client.Configuration" type="Folder" />
      <add path="Marketing.Xdb.MarketingAutomation.Operations" type="Folder" />
      <add path="Marketing.Xdb.MarketingAutomation.Reporting" type="Folder" />
      <add path="Marketing.Xdb.ReferenceData.Core" type="Folder" />
      <add path="Marketing.Xdb.ReferenceData.Client" type="Folder" />
      <add path="Marketing.Operations.xMgmt" type="Folder" />
      <add path="Marketing.Segmentation.xMgmt" type="Folder" />
      <add path="Marketing.Xdb.MarketingAutomation.Locators" type="Folder" />
      <add path="Marketing.Xdb.ReferenceData.Service" type="Folder" />
      <add path="Marketing.Xdb.ReferenceData.SqlServer" type="Folder" />
      <add path="Marketing.Operations.Xdb.ReferenceData" type="Folder" />
      <add path="Marketing.xDB" type="Folder" />
      <add path="Mvc" type="Folder" />
      <add path="Services.Client" type="Folder" />
      <add path="ExperienceContentManagement.Administration" type="Folder" />
      <add path="Speak.Integration" type="Folder" />
      <add path="Marketing.Tracking" type="Folder" />
      <add path="Tracking.Web.MVC" type="Folder" />
      <add path="Tracking.Web.RobotDetection" type="Folder" />
      <add path="Marketing.Assets" type="Folder" />
      <add path="Marketing.Xdb.MarketingAutomation.Tracking" type="Folder" />
      <add path="SPEAK" type="Folder" />
      <add path="Speak.Applications" type="Folder" />
      <add path="LaunchPad" type="Folder" />
      <add path="Experience Editor" type="Folder" />
      <add path="ContentTagging" type="Folder" />
      <add path="ListManagement" type="Folder" />
      <add path="Marketing.Client" type="Folder" />
      <add path="MVC.ExperienceEditor" type="Folder" />
      <add path="MVC.DeviceSimulator" type="Folder" />
      <add path="Personalization" type="Folder" />
      <add path="ContentTesting" type="Folder" />
      <add path="ExperienceProfile" type="Folder" />
      <add path="ExperienceExplorer" type="Folder" />
      <add path="SPEAK.Components" type="Folder" />
      <add path="ExperienceAnalytics" type="Folder" />
      <add path="CampaignCreator" type="Folder" />
      <add path="ExperienceForms" type="Folder" />
      <add path="ExperienceForms" type="Folder" />
      <add path="FederatedExperienceManager" type="Folder" />
      <add path="Marketing.Automation.Client" type="Folder" />
      <add path="Marketing.Automation.ActivityDescriptors.Client" type="Folder" />
      <add path="EmailExperience" type="Folder" />
      <add path="PathAnalyzer" type="Folder" />
      <add path="UpdateCenter" type="Folder" />
    </loadOrder>
  </layer>
  <layer name="Modules" includeFolder="/App_Config/Modules/" />
  <layer name="Custom" includeFolder="/App_Config/Include/">
    <loadOrder>
      <add path="Foundation" type="Folder" />
      <add path="Feature" type="Folder" />
      <add path="Project" type="Folder" />
    </loadOrder>
  </layer>

  <layer name="Aceik" includeFolder="/App_Config/Aceik/">
    <loadOrder>
      <add path="Foundation" type="Folder" />
      <add path="Feature" type="Folder" />
      <add path="Project" type="Folder" />
    </loadOrder>
  </layer>

  <layer name="Environment" includeFolder="/App_Config/Environment/" />
</layers>

Deploy to Sitecore and XConnect

Deploy the EXM helix project to Sitecore using your usual method. In my case, I used the publish option in Visual Studio and deployed the files to the website folder for my Sitecore instance.

To deploy the files to XConnect, this was not so simple. I manually deployed the following files to these locations in my XConnect instance:

  • sc.Aceik.Feature.EXM.Models.EmployeeModel.xml => \App_Data\jobs\continuous\AutomationEngine\App_Data\Config\sitecore
  • Aceik.Feature.EXM.dll => \App_Data\jobs\continuous\AutomationEngine
  • Aceik.Feature.EXM.Models.EmployeeModel, 1.0.json => \App_Data\Models

After deploying the files to XConnect, you will need to go and restart the XConnect services:

  • Marketing Automation Service
  • Processing Engine Service
  • Index Worker

Test the Import

Now that you have deployed the code and configuration changes to both Sitecore and XConnect, applied the Import Mapper configuration changes, you can now import your “Employees” from a CSV file. I have amended the CSV used in the Part 2 adding in the additional Employee specific columns:

email, firstname, middlename, lastname, gender, jobtitle, address1, address2, city, postcode, state, country,Employee ID,Department,Start Date,Employee Type
alberte@gmail.com,Albert,Basil,Einstein,Male,Scientist,Level 12,100 New York Lane, New York,25438, NY, US,FT0195,Science,23/01/1869,Fulltime
blaise@gmail.com,Blaise,Patricia,Pascal,Male,Mathematician,125 The Pond,,Paris,7321AE,PA, FR,CA0125,Mathematics,08/10/1915,Casual
cherschel@yahoo.com,Caroline,Jenny,Herschel,Female,Astronomer,34 The Strait,,Hanover,123BCF,Lower Saxony, DE,PT4567,Astronomy,05/05/1979,Permament Part-time
dorothyhodgkin@live.com,Dorothy,Anne,Hodgkin,Female,Chemist,87 Downing Street,,Westminister,SW1A,London,UK,FT0099,Science,13/08/1940,Fulltime
edmond145@facebook.com,Edmond,William,Halley,Male,Astronomer,114 ChittingHam Way,,Greenwich,SW1A,Kent,UK,CA0087,Astronomy,01/10/1985,Casual

I then imported these “Employees” using the same process as previously, with the only difference being that I now mapped the additional Employee fields.

Import from CSV file
Imported Employees

As you can see the Employees imported in the same manner as previously. Now, when I open the details of one of the Employees, I see no difference to before.

Contact Details

In the last and final part of this series, I’ll show you how to update the Experience Profile with a new Tab that you can use to display your custom Facet details. Click here for Part 4.

Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 2

In Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 1, I showed you how you can import contacts from a CSV file into a list in Sitecore EXM. Head over to Part 1 if you haven’t read that one as yet.

The properties of a contact that we are able to populate out-of-the-box are configured to the following fields:

  • Email
  • First name
  • Last name

Sitecore can be configured to support importing additional properties. In this article, I will show you how to update the configuration to support importing additional contact properties such as:

  • Middle name
  • Gender
  • Job Title
  • Address

Configure the Import Model

We need to first update the configuration of the import model. The import model is used to define the list of mapping fields that are displayed in the Contact Import dialog.

Start by launching the Sitecore Desktop from the Sitecore Launchpad. From there click on the master database in the lower right hand corner and select “core”. This switches the context to the core database. You can now launch the Content Editor by clicking on the Sitecore start button and selecting “Content Editor”.

Launch Sitecore Desktop
Switch to the Core database
Launch the Content Editor

In the Content Editor, navigate to the following path:

/sitecore/client/Applications/List Manager/Dialogs/ImportWizardDialog/PageSettings/TabControl Parameters/Map/ImportModel

Here you will see the list of configured field mappings. Will we now add to the list of field mappings by using the predefined available list of additional fields. Rich-Click on the “Import Model” node and using the Insert submenu, choose to add the following additional fields:

  • Personal – Middle name
  • Personal – Gender
  • Personal – Job title
  • Preferred Address – Address Line 1
  • Preferred Address – Address Line 2
  • Preferred Address – City
  • Preferred Address – Postal code
  • Preferred Address – State or Province
  • Preferred Address – Country code

The ordering of the fields is not mandatory but it’s worth putting into a logical order as this will be the order they are displayed in, in the contact import dialog.

Updated Import Model configuration

Now, go through the same process to create a new list and import the contacts from a CSV file. This time, when you reach the step of mapping the fields, you will notice there is additional fields to map. They are the new fields we just added to the Import Model is the previous step. Complete the mapping and the import as you did in the previous article.

Updated list of mapping fields
Updated list of mapping fields
Updated list of mapping fields

Now, when you open one of the imported contacts in Experience Profile, you will see the additional properties that have been imported:

Newly populated fields from the updated Import Model

In the Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 3, I will show you how to add custom properties to a Contact and have those properties populated via the Contact Import process.

Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 1

Are you a Sitecore developer looking to import contacts into Sitecore? Do you need to store properties for your contacts that are not supported out of the box by Sitecore?

In this multi-part series of posts, I will show you how you can import your contacts from a text file. I’ll show you how you can update the out of the box configuration to include importing other standard properties for your contacts. I’ll also show you how you can add your own custom properties for your contacts. And lastly, I’ll show you how you can update the Experience Profile UI so that your custom properties can be displayed for your contacts.

Contacts and Lists

Sitecore EXM supports the concept of both Contacts and Lists.

A contact itself is pretty self-explanatory and contains all the properties for the contact. Here are some of examples of the properties stored for a contact:

  • Email addresses
  • First, middle and last names
  • Gender
  • Birthday
  • Addresses
  • Job title

A list is simply a collection of contacts. A contact can be a member or a subscriber to multiple lists. Lists can be either static (a contact has been added to the list) or a list can be dynamic. Dynamic lists are populated based on a set of rules that uses the contact properties to determine if they should be a member of the list.

Importing Contacts

Out-of-the-box, Sitecore supports importing contacts from a CSV file. Your list of contacts to be imported need to have a minimum of the following fields:

  • Email address
  • First name
  • Last name

Sample CSV file

email, firstname, lastname
alberte@gmail.com,Albert,Einstein
blaise@gmail.com,Blaise,Pascal
cherschel@yahoo.com,Caroline,Herschel
dorothyhodgkin@live.com,Dorothy,Hodgkin
edmond145@facebook.com,Edmond,Halley

To import the contacts, go to the Sitecore Launchpad and click List Manager.

Once you are in the List Manager, follow these steps to import your contact list:

  • Click on the “Create” button
  • Select “Create list from file”
  • Click on the “Browse for a CSV file” button and select your csv file containing your contacts. Note: Make sure your file is named with a .csv extension
  • Enter a name for your list
  • Click on the “Upload file” button
Create a new list
Create the new list from a CSV file
Give your new list a name and upload the CSV file

Once the file has been uploaded, the process will prompt you to choose the mappings between the predefined Contact properties and the columns in your CSV file. If your CSV file contains columns you would like to use for the contact identifier and/or the identifier source, you can optionally check those and then be able to select the column mappings for those Contact properties.

Click “Next” to being the import process.

Nominate the field mappings

Once the import process has been completed, you will be shown a summary of what has been imported. When you click on the finish button, you will then be taken to your list that you have just imported. Here you can see the contacts that have been added to your new list.

Import Summary
Newly created list

You can also view the contact details by navigating back to the Sitecore Launchpad and launching the Experience Profile. There you can see the entire list of contacts. You can click into any of the contacts to see the details of the contact.

Experience Profile showing all your contacts
Contact details

There are additional properties that are shown in the experience profile that we can also populate via the CSV import process. To do that, we will need to customise the list of available properties that the importer allows to be mapped to.

In Sitecore Email Experience Manager (EXM), Importing Contacts and Custom Facets – Part 2, I will show you how you can customise that list of fields and import additional standard properties for each contact.

Sitecore personalisation doesn’t have to be complicated to drive business value

Key points:

  • Personalisation works, and must be on your digital roadmap
  • When starting out with personalisation many marketers are fearful of commencing because it can be complicated
  • How can you measure the effects of personalisation with minimal effort?
  • Start simple – test one example
  • Analyse the results
  • Learn from that test and set up another one
  • Over time you will have a body of personalisation that is validated, and will be generating greater value from Sitecore

Marketers have long known that connecting with their audience on a more personal level works. It generates higher engagement, leading to greater conversion rates and creating brand advocates.

When it comes to digital marketing, personalisation becomes even more powerful due to the amount of data now available on individuals, segments and their behaviour. Driving this forward are powerful Digital Experience Platforms like Sitecore, with a multitude of features enabling organisations to use the information they already have about a person and/or segment to create a more meaningful experience.

But if you’re new to digital personalisation, where do you start? With so many options available it can be a daunting task that it gets put off – thrown in the “too hard basket”.

The good news that even basic personalisation can generate significant increases in engagement and conversion rates. I always recommend to any digital marketer beginning their personalisation journey to start small, test and learn:

  • Begin with one hypothesis around one data point and implement that in isolation.
  • Ensure that there are enough visits to the personalised content to give a statistically relevant result.
  • Analyse those results to validate whether your hypothesis is correct.

A basic example I recommend is personalising content based on a website visitor’s location. Then deliver relevant content to those visitors based on their location. Sitecore XP comes with GeoIP location detection out of the box, and is simple to set up. One thing to note before attempting this is to ensure that your instance of Sitecore is configured correctly to use this feature. For more on this see the blog I wrote on Sitecore Optimisation Readiness.

Once confirmed that GeoIP detection is working correctly, here is one simple example that can be used to test the effect of personalising one small piece of content.

In this example (based on one of our clients), we will use an Australian company that has an audience mainly on the east coast. Visitors to its website are mostly from Victoria, New South Wales and Queensland.

They have recently released a research paper that is of interest to the vast majority of its audience. In order to get business outcomes from this valuable content, they require users to complete a registration form capturing basic information: name, email address and postcode. Upon completion of the form, they are provided with a link to download the paper.

On the initial registration page with the form, an image is shown next to the form. A generic version of the image is shown when a visitor’s location cannot be detected, or is outside Australia. If the visitor’s location can be identified, a different image is shown that is relevant to the state in which that visitor resides.

This is a relatively simple piece of personalisation, and only requires four different images to fully function – a generic image, and three images relevant to the three states.

By configuring a personalisation rule on that image component in Sitecore, results can be tracked to see the effectiveness of that personalisation.

One of our clients implemented a very similar campaign, and the results clearly showed that the personalised content outperformed the generic version by at least 40% in each personalised state.

This shows that any Sitecore user with relevant training on authoring and marketing in Sitecore could implement such a test and achieve improved results. This in turn shows your organisation the value of Sitecore and its features, which can lead to further investment in digital marketing campaigns.

For more information about Aceik’s Sitecore Optimisation Packages, please contact us at sitecoreoptimisation@aceik.com.au

Photo by Andrea Piacquadio from Pexels

Aceik & Sitecore’s Digital Wine-Down

Last week, Aceik and Sitecore brought together 16 digital experts from around Australia to discuss digital transformation – the trends, challenges and risks facing a new project in 2021. And it wouldn’t be a robust discussion without a wine tasting – kindly delivered by SocialTable and Price’s Wines.

Our moderator introduced two topics then guests were divided into groups of 6 to discuss. Upon return to the main track, guests then shared their unique discussion. And today, we wanted to share the key highlights.

Question 1

What are the biggest factors you think will influence investment and digital transformation over the next 12 months?

  • Customer-driven service channel
  • Being reactive to competitor demand
  • We’re not competing with competitors anymore, we’re competing with the most recent best experience the customer has had, and that’s the new benchmark
  • Depending on which industry the impact of COVID-19 varied (ie retail saw loads of money move into their ecommerce stores)
  • COVID-19 made getting sign-off easier on digital projects. Because digital was pretty much the only active channel
  • Increased emphasis on ROI now
  • Public sector using data in marketing campaigns
  • Coming out of COVID-19 lockdowns might be the perfect time to be disruptive

Question 2

What do you think are the biggest risks or pain points that companies aren’t aware of when embarking on a digital transformation project.

  • Budget 😊
  • Ensuring exec team is along on the journey
  • Lack of understanding of what digital transformation means
  • Finding the right agency to work with and trust
  • Exec team churn.
  • Getting staff buy in early
  • Ongoing costs of systems implementations not considered
  • Silo’d environments
  • Staff can be resistant
  • Defining success criteria
  • Lack of a clear project leader
  • Failing to train!

It was a fantastic event and we really appreciate the open sharing amongst the group!