Crawl, walk, run into digital marketing with Sitecore

Imagine this scenario: as an experienced digital marketer, you have multiple sources of acquisition: SEO, SEM, display advertising, print advertising, social media, and even offline events or tradeshows. All of those potential customers funnel into your website at various entry points and with varying moments in their decision life cycle. Your website, primed for these audiences, responds with the perfect message to each person, using data about that person, the campaign they responded to and their activity on your site to instantly deliver tailored content. Your site is perfectly tuned — thanks to A/B and multivariate testing — and linked to an engagement plan via marketing automation that gracefully leads the visitor through their purchase life cycle, ultimately delivering you a qualified lead or sales conversion. And on the backend, you have this amazing 360-degree view of that lead, includingevery interaction they have had with your brand. Sounds utopian, right? My guess is that you may have even been sold this vision before by one of the thousands of software vendors in the marketing technology landscape or an agency or SI that implements them.

Don’t get me wrong, it’s a great vision and it’s ultimately why we’re all in this business. Like all great visions, the challenge is getting from here to there. Most companies admit to being on the “immature” side of the Sitecore Customer Experience Maturity Model, somewhere around Initiate or Radiate. While there is more nuance to digital marketing maturity than found in the Sitecore model, it covers the basics. For marketers on the left side of the scale, the biggest challenge is knowing how to find the path to the right. It’s easy to stand still, in a state of paralysis.

So how do you get moving? Slowly. This is a marathon, not a sprint. And the speed with which you accelerate will depend on how quickly you and your organization can embrace new ways of thinking and new ways of doing. The formula is simple though: Crawl, Walk, Run.

Crawl

No matter where you start the race, you want to be sure you have the right shoes on – they’re the foundation for your journey:

You need a mobile-optimized, content-rich website. You need  a solid understanding of your audiences, their need states and their journeys through engagement with your site and brand. And you need to be on a current version of Sitecore with xDB enabled, configured and collecting data about your users’ interactions. Out of the box, Sitecore will provide you the basic analytics that you would typically find in a Google Analytics report. You’ll want to start by building on those base analytics: identifying goals and assigning values to them.  In Sitecore’s terms, these goals and their values become your Engagement Value Scale. They show the relationship between a given activity on your website and the likelihood to convert. Example goals in a B2B environment might include:

  • Visiting a product page
  • Downloading a product brochure or whitepaper PDF
  • Watching a product demonstration video
  • Signing up for a webinar
  • Requesting a demo or sample
  • Requesting a quote or sales contact

Each of the above goals is assigned a point value in Sitecore. So a visit to a product page might have a value of 1, while requesting a quote might have a value of 6. Sitecore lets you track each visitor’s journey toward conversion over the full sales cycle, providing you with the starting point from which you can build your digital marketing engagement plans.

Walk

With your fundamentals in place, you’re ready to implement the next set of capabilities: campaign management and testing.

Campaign Management

Campaign management is relevant for companies that do any type of email marketing, PPC, social media or display advertising. This capability allows you to track incoming traffic to your site from all of those sources, and measure the value of that traffic over time. Many analytics systems will provide the basic traffic reports by campaign, but fail to give you insight on how well those campaigns deliver on actually converting visitors. Sitecore’s campaign management capabilities track the value of a visitor throughout all touchpoints over multiple visits, giving you a clearer picture on the ROI on your advertising spend.

A/B & Multivariate testing

When you have a better understanding of engagement value, you can start optimizing your site for conversions. Sitecore offers both A|B and multivariate testing capabilities that enable you to  test individual components (or sections) of a page, or entire pages. Sitecore can automatically choose test winners based on your specific criteria, based on the engagement values that you set in your crawl stage.

Run

Every marketer’s goal is to deliver relevance, and personalized experiences are the “new normal” when it comes to being relevant to you target audiences. Sitecore enables both implicit and explicit personalization of digital experiences:

Explicit personalization changes your content and/or user experience based on information known about the visitor. Examples include the visitor’s location, their industry, the campaign they responded to, how many times they’ve visited, etc. You can create simple rules like, “if visitor responded to campaign ‘ABC’ then show this component. “Or you can create complex rules that combine many known facts, “if visitor is located in Texas and has visited the site at least 2 times and responded to campaign ‘ABC,’ then show this component.”

Implicit personalization changes the content or user experience based on information assumed or inferred about the visitor. For example: If a user just bought a vacuum cleaner on your website, you might assume that they also need vacuum cleaner bags, and you could display a special offer to them for bags. If a visitor is browsing a lot of content about caring for dogs, you might assume they are getting ready to adopt and show them dogs that are available in their area.

This type of personalization has the power to really reach visitors with content that is tailored to their interests, but it does require some legwork. I explore the details of personalization in my previous post “8 Steps to Start Your Personalization Journey

Most critically, understand that reaching that digital marketing pinnacle is truly a journey. You don’t get there overnight, and the pace at which you progress will depend in large part on how quickly you master each step along the crawl-walk-run. Avoid the temptation to try and do everything at once. Start with the basics (analytics & engagement value scoring); add campaign management & A|B testing; then move on to content and experience personalization. On each step of the journey, set benchmarks and success criteria, so you can understand and report on your progress, and you can revise your plan if you’re not meeting your goals. True marketing ROI is not that far off – this is how you get there!

Keeping Your Sitecore Tree Organized

There’s one big thing that should be on everyone’s mind when working with a lot of content.  That big thing is organization of the Sitecore content tree.  With a single site solution, organization can be a little less serious.  But, once you start to deal with a multi-site solution, organization is key.  There are so many different ways for a content tree to go from being very cleanly organized to being one of the most confusing things to try and navigate.  Admittedly, I like my content tree like how I have my folders on my computer, very organized.  That way, when you need to find something quickly, it is very easy.  If it’s disorganized, then it ends up being a longer process to find the item.  Which, multiplied by however many components you have on a page, could really affect how quickly you can create a site.  So, when I see a Sitecore tree that seems to have items spread out all over the place, I want nothing more than to help the client clean it up and give them the tools to keep it clean.

Component Tree 1

Let’s take a look at this screenshot.  In this multi-site solution, we have created components (or modules) to be added separately to the page allowing the content editor to essentially be able to build out a webpage from a blank slate.  So, due to the number of components that will be created, it is important to keep the components folder organized in order to quickly find the datasource you’re looking for.  As a developer, when setting up a components folder, one of the easiest, but more restrictive, ways is to create folders yourself and only allow the content editor to insert that type of component in that folder (eg. Creating a Rich Text folder and only allow a Rich Text component to be inserted below it).  This isn’t the way I wanted to implement this organization strategy since I didn’t exactly know if the client wanted them to be organized by site, by component type, by both, etc.  This way also doesn’t easily lend itself to growth since it’s more restrictive for the content editor.  So, a more flexible way to implement this is to create a new folder template and give all your components as an insert option to this folder.  But, the key step here is to also add the same folder template as an insert option as well.  This will allow the content editor to make folders as they please and organize the Sitecore tree to how it’ll make sense to them.

Component Folder Insert Options

Now, these were all ways as a developer to help the content editor.  But, a content editor should utilize these tools that the developer has implemented.  If a developer hasn’t implemented a good way to organize the Sitecore tree, it is absolutely worth asking.  This will only help out with confusion in similarly named components, identically named components that are different templates, etc (as mentioned in Keeping Item and Field Names Unique).  As a content editor, it is also worth thinking about how you want your data structured in Sitecore before you start building out your content.  This way, you could build out your folder structure logically before adding any sort of content.  If you don’t want the ability to create folders of your own, but want the restriction of only being able to add a specific component(s) under a certain folder, work with your developer and implement it together.  This way, you’ll have a way to organize your data that you’ll be happy with.  Personally, I’m a fan of giving the content editor the ability to structure their data as they please.  This allows the solution to easily expand if additional sites are added.  This also gives the ability for the content editor to change their mind about how the tree is structured.  Let’s say the content editor just wanted all the components to be grouped together regardless of site.  Well, after the content editor starts to get hundreds of components, that organization process may not be sustainable anymore.  Instead of needing to go to the developer and paying to have an additional ability to change how the content tree is organized, that ability is already there and the content author can alter that item structure without any negative effects to the site.

Component Tree 2

In the end, as a developer, the most important thing is to deliver a solution that the client is happy with.  Knowing full well that there will be some complex data that will need to be made easier for a content editor to work with, organization is key.  As you can see in the “Component Tree 2” screenshot, I have organized the components from the “Component Tree 1” screenshot into easier to understand folders by using the same insert options as shown in the “Component Folder Insert Options” screenshot.  If there are even more components, and there still are too many items under each folder, you can easily add another level of the site that they’re created for.  But, for this situation, just doing the one level is enough.  It is all dependent on how much content is going to be going into each site and how easily it is to understand where to find those items.

 

 

 

Keeping Item and Field Names Unique

There are many things that can help with confusion as a developer and as a content author.  One of the biggest confusions I’ve come across has been duplicate item names, fields, and placeholders.  Sitecore will render whatever the first instance of that name is.  So, if you have an item with the same name as another, it will render the one higher up in the tree.  The same idea expands to placeholders and field names as well.  There’s a way to work with the placeholders and not be required to create multiple placeholders that have the same function called “Dynamic Placeholders“. However, the other two require some discipline as a developer and a content author.

As a content author, to avoid general confusion, giving unique names to items will avoid a possible situation where content you’ve entered is not showing up properly or not at all.  I’ve run into a few situations where the client has asked me to troubleshoot why the content they’ve updated was not displaying like they were expecting.  When I started troubleshooting, I noticed that there were items that had the same name.  It turned out they were editing the lower of the items which meant the rendered content wasn’t actually updating.  In addition, I had also noticed that other renderings were missing content entirely.  After looking into this situation, I found out that there were different templates that were utilizing the same name as well.  So, the content author added a Rich Text block to the page and correctly pointed the Datasource.  However, the item above it was an Accordion template that shared the same name.  Since Sitecore uses the path to get to the Datasource as opposed to a GUID, the rendered page was trying to render the Accordion template in the Rich Text rendering, which didn’t render properly.  One of the easiest ways to do this is to either put all items that belong together in a folder or name each one differently but name them in a way that a content author will understand that they go together (see green highlighted area).

As a developer, however, one of the things that will avoid general confusion for content authors is to name your template fields well.  Naming something “Content” can work if you’re creating a template that’s going to be inherited in to multiple places.  However, if you are creating a field specifically for a template type, it’s worth naming your fields more specifically.  As you see in the screenshot, there are two fields named “Page Title”.  One field is being inherited while the other field was added to the template itself with the same name.  This means, the first one will be the field that gets rendered while the second one is about as useless as it can be.  To avoid these types of situations, it’s good to plan out your templates before you create them to see what fields are being inherited and what fields you’ll need to create.

Sitecore UserName & Password Hardening

All organizations have processes & procedures in place to reduce the surface of vulnerability. One of the way to reduce attacks typically includes having a password policy and Sitecore Experience Platform is no exception to it. The way by which one installs Sitecore and configure has a significant effect on the security of a website. Sitecore has in place a fair amount of documentation related to Security Hardening and Sitecore Security Hardening Guide. Recently I was working on a Request For Proposal (RFP) which had lot of questionnaire related to password policy, I was aware that password policy can be enforced for Sitecore but was not satisfied that I have complete details and specifics to implement the password policy.

This blog post is about a voyage “Sitecore Username & Password Hardening” during which I drilled down the information for various settings and options available in Sitecore related to username and password policy implementations. If you are interested to harden a Sitecore implementation join me on this voyage and keeping reading the blog post further.

There are good number of documents & blogs, see “Nice Reads” section of this post for all such details.

Let’s start with some fundamentals to be aware about,

  1. Sitecore uses .NET security engine and is built on top of .Net Membership Provider
  2. All information related to roles, users, passwords and access is stored into “core” database. Hah! Why am I writing this should this not be known? Well trying to share information and making sure I cover all audiences for the post from including starters, mid-level and experienced Sitecore geeks.
  3. It is possible to replace or extend default configurations by writing a custom provider.

Let’s start with some specifics now,

UserName

Jason’s post USING EMAIL ADDRESSES AS YOUR SITECORE USERNAME is almost a clone of Brian’s post Sitecore allow email adress as user name

Rhys Godfrey’s post Sitecore–Changing the Username validation rule is all you have to understand for setting by UserName Validation.

I do not want to bombard duplicated information.

Password

Q. Have you been asked to setup and enforce password policy?

Q. How to configure it for Sitecore?

Q. Where to start?

A. Here’s the answer, as said earlier Sitecore is built on .Net Membership provider start by looking <configuration>/ <system.web>/<membership> section of a web.config file on your Sitecore installation.

Q. What I need to look for?

A. The “sql” provider and the attributes of the provider.

Attributes Value Type
minRequiredPasswordLength int
minRequiredNonalphanumericCharacters int
requiresQuestionAndAnswer bool
requiresUniqueEmail bool
maxInvalidPasswordAttempts int
 passwordAttemptWindow int
enablePasswordRetrieval bool
passwordFormat string
passwordStrengthRegularExpression string

 

  • minRequiredPasswordLength : The attribute name itself is self-explanatory, it allows to specific the minimum number of character a password should have. The default value is 1 and of-course it cannot be 0 otherwise you will see below error,

1) minRequiredPasswordLength

What happens when some tries to setup password where length is less than minimum required?

Sitecore displays message and makes you aware of possible reasons,

Reasons

  • minRequiredNonalphanumericCharacters: Specify minimum number of non-alphanumeric characters a password must contain.
  • requiresQuestionAndAnswer: Sitecore do not support this attribute and setting it to true will not allow for creation of a new user.

3) requiresQuestionAndAnswer

  • requiresUniqueEmail : Validates if there is already another user with same email address or not. If found New User will not be created and a message will be displayed.

4) requiresUniqueEmail

  • maxInvalidPasswordAttempts: User will be locked out after sur-passing the number of times an incorrect password is specified for login to Sitecore.

Sitecore login page do not specifically mentions about the user being locked out.

maxInvalidPasswordAttempts

The information for a “Locked Out” user is available in User Manager,

locked out

  • passwordAttemptWindow


The PasswordAttemptWindow property works in conjunction with the MaxInvalidPasswordAttempts property to help guard against an unwanted source guessing the password or password answer of a membership user through repeated attempts. When a user attempts to log in with, change, or reset his or her password, only a certain number of consecutive attempts are allowed within a specified time window. The length of this time window is specified in the PasswordAttemptWindow property, which identifies the number of minutes allowed between invalid attempts.

If the number of consecutive failed attempts that a user makes to reset his or her password equals the value stored in the MaxInvalidPasswordAttempts property, and the time elapsed since the last invalid attempt is less than the number of minutes specified in the PasswordAttemptWindow property, then the membership user is locked out. The user is locked out by setting the IsLockedOut property to true until the user is unlocked by a call to the UnlockUser method.

If the interval between the current failed attempt and the last failed attempt is greater than the PasswordAttemptWindow property setting, the current invalid attempt is counted as the first. If a valid password answer is supplied before the maximum number of allowed invalid attempts is reached, the count of invalid password-answer attempts is set to 0 (zero). If a valid password is supplied before the maximum number of allowed invalid attempts is reached, the count of invalid password attempts and the count of invalid password-answer attempts are set to 0 (zero).

So for example if the values set for the attributes are maxInvalidPasswordAttempts=”5″ passwordAttemptWindow=”1”. A user will be locked out after he makes 5 unsuccessful attempts. If the user has made less 4 unsuccessful attempts and then he/she tries after “passwordAttemptWindow” (in our example 1 minute) the user will not be locked out as the attempt would have been set to 0 counter.

  • enablePasswordRetrieval
  • This attribute holds a value indicating whether the current membership provider is configured to allow users to retrieve their password. Default value is false and if you turn it on you might see below error as this attribute works in conjunction with passwordFormat.
  • enablePasswordRetrieval
  • passwordFormat
  • This attribute describes the encryption format for storing passwords for users. The values can be,
    Attribute Value Description
    Clear Not secure, do not use. Passwords are not encrypted.
    Encrypted Not secure, do not use. Passwords are encrypted using the encryption settings determined by the machineKey Element (ASP.NET Settings Schema) element configuration.
    Hashed Passwords are encrypted one-way using the SHA1 hashing algorithm.

    Hashed is the default one!

    How does it looks in Membership database (MS SQL) when these formats are changed?

    Below image is for “Clear” format

  • Clear
  • Below image is for “Encrypted” format
  • Encrypted
  • passwordStrengthRegularExpression
  • The PasswordStrengthRegularExpression property gets the regular expression used to evaluate password complexity from the provider specified in the Provider property. This is one of the most important attribute that would allow to implement strict password policy and set various rules related to passwords like,
    • Is greater than seven characters.
    • Contains at least one digit.
    • Contains at least one special (non-alphanumeric) character.

    All the above attributes are considered while a user is being setup into Sitecore from User Manager. Sitecore Login page ignores these attributes and just validates if the username and password is correct which make sense as otherwise consider a case that users were already setup and later on password policy was enforced to have at least one non-aplhanumeric character. Such users will not be able to login even if their password matches to whatever it’s is stored in database.

    I collected information related to sql provider from Membership Class and if you are looking for more information here is the place where you should watch out for.

    Nice Reads

A/B testing with Sitecore Email Experience Manager (EXM)

How to do A/B testing with email campaigns in Sitecore?

A/B testing  any email campaign is the best way to ensure that you are giving customers the information they want to see. As you create email campaigns, you are probably placing the content and messages layout based on the assumptions that you feel is appealing to the customer. However, your assumptions might not be accurate, and your recipients might not respond to your campaign in the way you expect them to. A/B testing allows you to create a couple of variations of the similar message so that you can send it to a small group of people first and see how they interact with the message and which one gains more popularity before picking the final message to be sent to your entire email base.

Sitecore Email Experience Manager (EXM) guides through the process of A/B testing but please consider the following factors before you start A/B testing:

  • Decide on the number of recipients to be included in the email campaigns (always include a small pool of recipients in the test to get a reliable result)
  • Confirm on which part of the messages needs to be tested for e.g. either the subject line or any components in the content area, text, links, images etc.
  • Decide on the number of variants to be included in the A/B test. Always consider the number of recipients proportional to the number of variants.
  • Selection of the message variant winner can be either manual or automatic

When you want to run an A/B test, you need to create variants of the original message campaign:

To create a new variant of a message:

  1. Open the message for which the A/B test needs to be performed.
  2. You can add a new variant or duplicate the original variant and all its content also modify it.
    • To add a new variant for the message, go to the message tab, click Add Variant img as per the screen-grab:

      img_15

    • This creates a new message variant based on the same template as the original message but no content will be replicated.

      img_8

    • If we need to duplicate the original message variant then click the arrow button next to quick test tab and select the “Duplicate this variant” option. This option can be chosen if you want to test minor differences between variants such as subject line, name of a button or image.

      img_4

    • Message variants are displayed just below the tabs and you can easily toggle between the variants.

      img_9

    • Please note that you can create as many variants of the message, but when you add more variants you need a larger pool of recipients for the test results to be clear and reliable. Hence it’s recommended to test against maximum of two or three variants.
  3. Make the necessary changes to the new message variant. Once done with the changes to all the variants click Save.

Start an A/B test:

Next go to the Delivery tab of the relevant message, select the variants which you want to be included in the A/B test. For this example here, the variants A and B are selected.

img_9

Following options are seen under the Delivery tab:

Size of the test: From the drop down menu, select the percentage of recipients that needs to be included in this test. This set of recipients will be randomly generated from the full list of recipients.

  1. Select Winner: There are two options by which you can specify how the winner can be chosen.
    • Automatic: By choosing this option, the system selects the winning variant based on either best value per visit or highest open rate. Also here you need to specify how long you want the test to run before the winner is selected.
      • If you select “Best value per visit” the winning variant is based on the one that generates the most value on the website per visitor.
      • If you select the “Highest open rate” the winning variant is the one that was opened the message most often.
    • Manual: This option allows you to review the reports of the A/B test and select the winner based on your own criteria.
  2. Schedule Delivery:
    It lists down the following options:

    • Send message now: It starts the A/B test immediately.
    • Schedule message delivery: It schedules the delivery of the A/B test message for a later time. Here you can specify the date and time to start the A/B test.
    • Schedule a recurring delivery: This option allows to send the A/B test message recurrently at a certain interval, date and time.
  3. Notification: Clicking the Notification check box allows you to send a notification as shown below to the specified email address regarding the completion of A/B test.

    img_10

  4. Multi-language: Clicking the More option, gives the Multi-language option. It allows you to send the message to the recipients’ preferred language.

Once done with selecting the setting under the Delivery tab, click on Start A/B test button at the bottom (Schedule test button in case of scheduled A/B test)

img_11
Clicking on Start A/B test button gives the below screen which confirms whether the A/B test needs to be sent to all the included recipients.

img_12

Depending on the option chosen as a method for winner selection (Manual/Automatic), the winning variant get selected.

If the winner is to be selected automatically then after the specified time has passed the EXM sends out the winning variant automatically to rest of the recipients in the recipients list.

Please note that wining message will not be sent to any of the recipients that were included in the A/B test.

If the winner needs to be selected manually then review the A/B test reports and select the variant which is best to be sent out. For the manual option each variant is listed with current achieved statistics:

  • Open rate: This displays the percentage of recipients that have opened the message.
  • Click rate: This is percentage of recipients who have clicked the link in the message.
  • Value: It is the engagement value points generated after the recipients have opened the message.

Based on the results for open rate, click rate and value one can decide which variant will be the best and then click ‘Choose as winner’ option. For e.g. here Variant A has been selected as the winner would give pop up dialog box to confirm.

img_13

This is will then send out the winning message to all the rest of recipients. Below is screen grab of the sample email which the recipients will receive.

img_14.jpgIf you need more detailed information on the A/B test results, click the Reports tab which details about the recipient behavior and message performance.

Reports

Query Sitecore xDB MongoDatabases via RoboMongo Part 3

In my previous two blog post Query Sitecore xDB MongoDatabases Part 1, I shared information about configuring RoboMongo for making it to understand CSUUID and the second post Query Sitecore xDB MongoDatabases Part 2 informing about executing queries from Mongo Shell. This post would be the last in the series where I would share queries that would be handy to be executed from RoboMongo. One would wonder as to why mentioning queries if already there is a blog post out there for Mongo Shell. There are few differences in the syntax for RoboMongo and Mongo Shell and hence this post.

Differences

The differences that stands out for queries for Mongo Shell vs RoboMongo are,

  • Instead of referring to the collection name COLLECTION_NAME.find() as compared to Mongo Shell, RoboMongo uses getCollection method.
  • GUIDS would have to be enclosed in the call for CSUUID for e.g CSUUID(“7801dccd-6d8c-4c6e-8327-f66a7c773698”)

Similarities

  • Similarity is both Mongo Shell and RoboMongo are case sensitive so .find({}) and .Find({}) are interpreted differently where former is correct to search for a record and the later would result in an error. Case sensitivity holds true for fields names too so finding a record for “ContactID” would get you results but not for “contactid”
  • find, and, or, sort and limit syntax is similar for Mongo Shell and RoboMongo.
  • Fields hierarchy separated by “.”

find()


db.getCollection('Contacts').find({})
Query for GUIDS
 db.getCollection('Contacts').find({"_id" : CSUUID("7801dccd-6d8c-4c6e-8327-f66a7c773698")})

RoboMongo-Guid

Query for data without GUIDS. Fields hierarchy separated by “.”

 db.getCollection('Contacts').find({"System.VisitCount" : 6})

RoboMongo-Field

Note: _id from Contacts collections maps back to ContactId in Interactions collection


db.getCollection('Interactions').find({"ContactId" : CSUUID("7801dccd-6d8c-4c6e-8327-f66a7c773698")})

and


db.getCollection('Contacts').find({$and:[{"System.Value":0},{"System.VisitCount":10}]})

RoboMongo-and

or


db.getCollection('Contacts').find({$or:[{"System.VisitCount":6},{"System.VisitCount":10}]})

RoboMongo-or

sort()

--For descending order.
db.getCollection('Interactions').find({"ContactId" : CSUUID("7801dccd-6d8c-4c6e-8327-f66a7c773698")}).sort({"SaveDateTime":-1})
--For ascending order.
db.getCollection('Interactions').find({"ContactId" : CSUUID("7801dccd-6d8c-4c6e-8327-f66a7c773698")}).sort({"SaveDateTime":1})

limit()


db.getCollection('Interactions').find({"ContactId" : CSUUID("7801dccd-6d8c-4c6e-8327-f66a7c773698")}).sort({"SaveDateTime":-1}).limit(3) can be used for fetching top 3 records.

Sitecore PXM 8.0: Add Vulgar Fraction Support

Background

Sitecore Print Experience Manager (PXM) is great; you can create dazzling printable documents that reuse your existing Sitecore content. You can enable your designers to add a personal touch to each document, or configure automation to allow document creation on the fly.

One of the primary components of PXM is its InDesign Connector plugin (IDC). It facilitates communication between Sitecore PXM and InDesign, allowing a designer to:

  • add Sitecore content to an existing InDesign document
  • create and update PXM Projects, which are a Sitecore representation of an InDesign document
  • manipulate master documents, which are essentially InDesign templates
  • save content changes directly into Sitecore items

“Vulgar” Fractions

Vulgar fractions are simply fractions that are “non-standard.” Examples of standard fractions are below. These are the ones Sitecore PXM supports out-of-the-box:

  • &frac14; – ¼
  • &frac12; – ½
  • &frac34; – ¾

There are a whole host of others, however, that can be added. Some include:

  • &frac18; – ⅛
  • &frac35; – ⅗
  • &frac56; – ⅚

How To Add Support for the Vulgar Fractions to PXM

  1. Open Website\Print Studio\Data\special.xml – this is the file that is used to map an HTML code (e.g. &frac18;) to the corresponding UTF-8 character value (e.g. 8539).
  2. If you want to keep your file (roughly) in order by index, scroll down to the entry with index=”8501″.
  3. Insert the following elements:
     <codeposition index="8528" entity="frac17"/>
     <codeposition index="8529" entity="frac19"/>
     <codeposition index="8530" entity="frac110"/>
     <codeposition index="8531" entity="frac13"/>
     <codeposition index="8532" entity="frac23"/>
     <codeposition index="8533" entity="frac15"/>
     <codeposition index="8534" entity="frac25"/>
     <codeposition index="8535" entity="frac35"/>
     <codeposition index="8536" entity="frac45"/>
     <codeposition index="8537" entity="frac16"/>
     <codeposition index="8538" entity="frac56"/>
     <codeposition index="8539" entity="frac18"/>
     <codeposition index="8540" entity="frac38"/>
     <codeposition index="8541" entity="frac58"/>
     <codeposition index="8542" entity="frac78"/>
    
  4. Recycle the Sitecore PXM AppPool.

Bonus

If you're curious, this configuration is used by the Sitecore.PrintStudio.PublishingEngine.Text.Parsers.Html.HtmlEntityHelper to map between the HTML code  (e.g. &frac18;) to the corresponding UTF-8 character value (e.g. 8539).