This document shares best practices that Marketing Cloud Personalization template developers follow for writing consistent HTML (Handlebars), CSS, and JavaScript code. Use this documentation as a guide for developing your own templates.
Handlebars HTML
HTML Syntax
Indent nested elements 4 spaces (one press of the TAB key in the template editor).
Break long lines to improve readability, up to 120 characters maximum per line. Place HTML attributes that extend beyond 120 characters on a new continuation line, indented 4 spaces.
Use double quotes ( "" ) instead of single quotes ( '' ) for HTML attributes, as shown in the following example.
Contain all the handlebars HTML content within a single element.
Write all code in lowercase, including HTML element names, attributes, and attribute values.
Use HTML elements for their designed purpose. Whenever possible, use semantic elements that describe the meaning of the content. See the section on “Accessibility” for more details.
ID and Class Nomenclature
Add an ID attribute to the outermost element, using a name specific to the template being built, and prefix with the evg- namespace (for example, id=“evg-hero-banner”). Use an ID for only this outermost HTML element and do not use the same ID in more than one template.
Use classes for all other nested elements. Prefix classes with the evg- namespace (for example, class=“evg-btn”).
Use hyphens to separate words in class and id names.
For suggested evg- prefixed class names and descriptions of their intended purpose, as well as examples of CSS styling, refer to Template HTML Classes and CSS.
Attributes Order
List your HTML attributes in the following order to improve readability.
class
id, name
data-*, data-evg-*
src, for, type, href, value
title, alt
role, aria-*
style
Campaign Stats Tracking
If you would like to track campaign stats with Personalization, use the data attributes (data-evg-*) available in the Handlebars HTML. These data attributes require that the Campaign Stat Tracking gear is installed and enabled for your dataset.
See the Campaign Stats article on this site to learn more.
Comments
For comments you wish to keep in the Handlebars-generated HTML output, use the native HTML comment format:
1<!-- This comment will show up as a HTML comment -->23<!--4 This comment will also5 show up as a HTML comment6-->
For comments you wish to remove in the resulting HTML output, use the following Handlebars HTML comment format.
1{{! Single-line comments go here. This comment will not appear in the HTML output}}23{{!4 Multi-line comments go here.5 This comment will not appear in the HTML output.6}}
Any Handlebars HTML comment that includes double curly braces or Handlebars expressions must adhere to the following format. These comments also do not appear in the resulting HTML output:
1{{!-- This comment can contain }}, {{, or {{ ... }} --}}23{{!--4 Multi-line comments go here.5 This comment will not appear in the HTML output.6 {{ handlebars expression }}7--}}
Place the leading brace on the same line as the selector.
Single-line comment
1/* bad */2#evg-banner .evg-cta3{4 color: red;5}67/* good */8#evg-banner .evg-cta{9 color: red;10}
Add one space between the colon and value of each property. No space before the colon.
Single-line comment
1/* bad */2#evg-banner .evg-cta{3 color:red;4}56/* bad */7#evg-banner .evg-cta{8 color :red;9}1011/* good */12#evg-banner .evg-cta{13 color: red;14}
For each declaration, indent 4 spaces (one press of the TAB key in the template editor) and include a single space after the colon. End each declaration with a semicolon ( ; ). Add a blank line between rulesets.
Add one space before the leading brace.
Single-line comment
1/* bad */2#evg-banner .evg-cta{3 color: red;4}56/* good */7#evg-banner .evg-cta{8 color: red;9}
Use the ID selector of the outermost element for every CSS rule to scope them all to the specific template. Use classes instead of element names as selectors that follow the ID selector.
Write code in lowercase, including selectors, properties, and property values (except for strings).
Single-line comment
1/* bad */2#evg-banner .evg-message{3 color: #CED5DF;4}56/* good */7#evg-banner .evg-message{8 color: #ced5df;9}
Avoid using element names in conjunction with IDs or classes. Also avoid using ancestor selectors unless necessary.
1/* bad */2div#evg-banner{3 color: red;4}56/* good */7#evg-banner{8 color: red;9}1011/* bad */12body div .evg-cta{13 color: red;14}1516/* good */17.evg-cta{18 color: red;19}
Don’t add units for “0” values, unless required.
1/* bad */2p{3 margin: 0px 10px;4}56/* good */7p{8 margin: 0 10px;9}
Don’t add leading zeros in property values.
Single-line comment
1/* bad */2p{3 font-size: 0.9rem;4}56/* good */7p{8 font-size: .9rem;9}
Declaration Order
Group properties by type, in the following order:
Positioning
Display / Box Model
Color
Text
Other
Example:
1#evg-home-hero-banner .evg-btn{2 position: absolute; /* Positioning */3 z-index: 10; /* Positioning */4 top: 0; /* Positioning */5 left: 0; /* Positioning */6 display: inline-block; /* Display and Box Model */7 box-sizing: border-box; /* Display and Box Model */8 width: 100px; /* Display and Box Model */9 margin-bottom: 10px; /* Display and Box Model */10 padding: 10px 5px; /* Display and Box Model */11 border-radius: 5px; /* Display and Box Model */12 color: #fff; /* Color */13 background-color: #215ca0; /* Color */14 font-size: 16px; /* Text */15 font-family: Arial, sans-serif; /* Text */16 text-align: center; /* Text */17 text-transform: uppercase; /* Text */18 transition: color 0.15s; /* Other */19 cursor: pointer; /* Other */20 user-select: none; /* Other */21}
Comments
Use /* ... */ for comments.
Single-line comment
1/* Comment goes here */2p{3 color: white;4 background-color: blue;5}
Depending on the SDK namespace you’re using, use SalesforceInteractions.DisplayUtils.pageElementLoaded or Evergage.DisplayUtils.pageElementLoaded to defer the rendering of the template until the content zone element is loaded on page. To use this utility, you must have the Display Utilities gear installed and enabled for your dataset.
The observer element that monitors for the content zone element to get inserted into its DOM node is set to “body” by default. For performance optimization, this default can be overridden by adding a second selector argument, which is used as the observer element instead.
SalesforceInteractions Namespace
1return SalesforceInteractions.DisplayUtils.pageElementLoaded(selector).then(function(element){2 const html = template(context);3 SalesforceInteractions.cashDom(element).html(html);4 applyTheme(context);5});
Evergage Namespace
1return Evergage.DisplayUtils.pageElementLoaded(selector).then(function(element){2 const html = template(context);3 Evergage.cashDom(element).html(html);4 applyTheme(context);5});
Follow the JSDoc standards for adding JavaScript documentation comments.
Use //... for inline comments.
1const foo = function(){2 const x = 4;3 const y = x + 2; // assign the sum of x + 2 to y4};
Use /** ... */ to comment code blocks, placed it immediately before the block being documented. For multi-line comments, align the stars by indentation.
Document code blocks with one or more JSDoc tags to describe the function.
1/**2 * @function incrementDate3 * @description Increment the date by a given number of days.4 * @param{string} date - The date, in MM/DD/YYYY format.5 * @param{number} days - The number of days to increment by.6 * @return{string} The new date, in MM/DD/YYYY format.7 */8function incrementDate(date, days){9 // ..10}
Use HTML elements for their designed purpose. Whenever possible, use semantic elements to describe the meaning of the content to developers and the browser when appropriate. For example, use heading elements such as h1, h2, and so on to identify headings, anchor elements (a) for navigation between pages, button elements (button) for actions like opening a modal, and input elements (input) for submit buttons (with the type="submit" attribute).
Semantic element examples:
button
h1
form
header
Non-semantic element examples:
div
span
If you use non-semantic elements instead of semantic elements, add ARIA attributes to provide more meaning to the element. For example, if you use a div element instead of the h1 element as a level 1 heading and there is more than one heading on the page, add the role="heading" and aria-level="<heading level number>" ARIA attributes to the non-semantic element (for example, <div role="heading" aria-level="1">Page Heading</div>). Doing so allows assistive technologies like screen readers to identify the non-semantic element as a heading.
Provide an alt attribute for all image elements. In case an image fails to load, the text alternative can convey the meaning of the image in its place (for example, alt="Woman with a shopping cart"). Aim for succinct, descriptive text. If the image is used purely for decoration and is not informative, set the alt tag to an empty string (for example, alt="") so that it can be ignored by assistive technologies. Do not leave out the alt attribute as some screen readers resort to announcing the file name of the image.
For close buttons (‘X’) such as those commonly used in popups, use a button element (button) with an aria-label attribute (for example, aria-label="Close") to provide an accessible name.
The WAVE Evaluation Tool Chrome extension is useful for evaluating the accessibility of your site.
Ensure that the colors chosen for the text and background satisfy the color contrast ratio as recommended by Web Content Accessibility Guidelines (WCAG). Aim for a color contrast ratio of 4.5 or higher for normal text and 3 for larger text (18 px in bold or 24 px). Visit the WCAG documentation on minimum contrast to learn more.
Use a tool like aremycolorsaccessible.com to check that the color ratio meets at least the AA level.
When using a background image as the backdrop for text, set a fallback background color in case the image does not load. Choose the fallback color such that the text is still visible and the colors meet the color contrast ratio requirements.