Skip to main content

The content rendering service

The content rendering service automates the process of combining JSON content with handlebars templates to generate HTML that can then be added to a page on your website. The service provides an API that takes a content or slot ID and a handlebars template as parameters and returns HTML in the response. The HTML can then be combined with CSS styling to display on your website or stored in an e-commerce system.

Using the content rendering service reduces the number of steps it takes to retrieve slots and content items from Dynamic Content and convert them into HTML. The service is optimised for use from server side code.

This page will explain how to use the new service in detail, including examples. For more details on the process of retrieving data without using the Content Rendering service see the Content Delivery 2 overview page.

The Salesforce Commerce Cloud and Salesforce Marketing Cloud integrations make use of the content rendering service. It's also used in the Dynamic Content to SAP connector.

Using the content rendering service
Link copied!

Both slots and individual content items are stored as JSON content and retrieved using their unique ID.

The steps to retrieve content from the Dynamic Content using the content rendering service are as follows:

  • Send a Get request to the content rendering service with a slot or content ID and a handlebars template as parameters

  • If the content is found then HTML is returned in the response

API reference
Link copied!


Link copied!

Link copied!

storeReplace this with your company tag. You can find this by looking at the dynamic URL of an asset published in Content Hub
idThe unique content ID for a piece of content included in your account
templateThe name of a handlebars template. This must be uploaded to your account as a text or HTML file

Status codes
Link copied!

Status codeDescriptionResponse
200OK. Content was found, template was found and HTML was generatedHTML
400Bad Request. Empty store / id or template name fieldPlain text
404Not Found. Could not find the template providedPlain text
404Referenced partial template not foundPlain text
500Server Error. Recursive template / Maximum template depth reachedPlain text
500Server Error. Recursive content graphPlain text
500Server Error. Handlebars processing errorsPlain text handlebars error message
500Server Error. Crashes of any kindPlain text

Link copied!

HTML should only be added to the page if a status code of 200 is returned. In all other cases the error should be trapped and appropriate action taken.

The URL above retrieves published content. To work with a mixture of unpublished and published content, replace with the domain of a virtual staging environment, for example, if the staging domain is then the URL would be as follows:

Link copied!

Handlebars is an off the shelf templating technology that allows developers to specify the structure of the HTML generated from a piece of JSON content.

The content rendering service includes the built-in handlebars features, such as loops, ifs and conditional branching, but also includes a number of other utilities, or helpers, that developers may find useful in structuring their templates.

Supported helpers
Link copied!

We have included most of the helpers defined in the handlebars helpers GitHub repository and the full list of supported helpers is shown below.

  • 'array'

  • 'collection'

  • 'comparison'

  • 'date'

  • 'html'

  • 'markdown'

  • 'math'

  • 'misc'

  • 'number'

  • 'object'

  • 'regex'

  • 'string'

  • 'uri'

Markdown helper
Link copied!

The markdown helper makes it easier for developers to convert text entered by users in markdown format, such as in a blog content item, to HTML.

Markdown text should be included within #markdown blocks in a handlebars template. In the example handlebars template below, the content type has a property called "blogtext" that contains markdown text.

{{#markdown blogtext}}{{/markdown}}

If the blogtext property contained the following markdown:

# This is heading 1

## This is heading 2

### This is heading 3

it would be converted into the following HTML:

<h1>This is heading 1</h1>
<h2>This is heading 2</h2>
<h3>This is heading 3</h3>

Handlebars templates
Link copied!

Templates are uploaded to Content Hub as .txt or .html files. You can also create the templates directly in Content Hub using the Text Editor app. A template must be published so that it can be used by the content rendering service.

An example template is shown below. This is used to structure the HTML for the tutorial banner slot and we've uploaded it to Content Hub as 'banner_slot_template.html'.

{{#with bannerslot}}
<div id="contentRender"></div>
<div class="banner">
<div class="banner-editorial">
<div class="banner-header">{{headline}}</div>
<div class="banner-subheader">{{strapline}}</div>
<a class="banner-call-to-action" href="{{calltoactionurl}}"

If we know that a piece of content is a banner, then we can make a request to the content rendering service as follows:

where 7ba216e9-7db2-41fa-ba0b-e1833f162be0 is the slot ID of this piece of content and banner_slot_template is the name of the template. Replace "ampproduct" with the name of your store.

The disadvantage of referencing a specific handlebars template for a particular slot or type is that you have to know that the content is a banner. You would have to use a different URL for each content type and this makes the code more difficult to maintain. That's where the handlebars partials feature is useful.

Link copied!

Partials is a handlebars feature that allows one template to load another. This lets you create a structure where you have one or more top level templates and separate templates for each content type, so you can specify the same template in each call to the content rendering service.

Partials are a useful way of structuring templates to allow for re-usable code. Your content types are likely to load a number of partials that are shared between several different types. For example a banner might load a button partial or an image partial.

The partials syntax is as follows:

{{> partialName}}

In order to make full use of partials, you also need to be able to determine the content type, so you know which template to load in. You would then end up with a top level template such as:

{{#if (test this.[@type] (toRegex ".*/tutorialbanner")) }} {{> banner_template
}} {{/if}} {{#if (test this.[@type] (toRegex ".*/featurevideo")) }} {{>
video_template }} {{/if}}

In this example banner_template and video_template could then load further partials depending on how you structured your templates. The template matches the content type with the corresponding handlebars template and then loads in the right one, in this case either a banner or a video. So, if we called our top level template 'top_template', we would make a request to the content rendering service.

and the correct template would be chosen to render the content.

When a new content type is added, you'd just upload it to Content Hub and update the top level template, in this case content_template, with the new content type ID.

Referencing the content type in a handlebars template
Link copied!

The content type shown in the handlebars template above is the content type URI, specified when the content or slot type is registered with a hub. If you want to make use of partials to organise your handlebars templates, then you will need to name your content and slot types so you can choose the appropriate template based on the content type name.

Handlebars versions
Link copied!

We currently use the following handlebars versions:

  • handlebars: 4.7.7
  • handlebars-helpers: 0.9.8

Link copied!

To maintain performance, there are certain limits imposed by the content rendering service. For each call, you are limited to 50 distinct templates. The service is limited to loading 50 distinct templates per call. 1000 partial loads. However, you are unlikely to hit these limits in normal usage.

Using the content rendering service example
Link copied!

In this section we've included an example of using the content rendering service, including some JavaScript code and sample templates.


The simple example below shows how to access the content rendering service from front end code. Note that the service is optimised to be used from server side code and that’s generally how we recommend it's used.

JavaScript code
Link copied!

Here's some JavaScript code that makes a request to the content rendering service. In this case the slot ID is 7ba216e9-7db2-41fa-ba0b-e1833f162be0 and we know the content is a banner slot. To try out this code, add the tutorial banner slot type to your account, add some content and add the slot or content ID for that piece of content to the request. You also need to change 'ampproduct' to your company tag.

// 'ampproduct' in the URL below should be replaced by the customer's publishing endpoint name.
// This will be shown in the Dynamic URL of any published asset in Content Hub.

const slotID = '7ba216e9-7db2-41fa-ba0b-e1833f162be0';

const contentUrl =
'' +
slotID +

// create and issue the request to the Amplience content rendering service
const deliveryRequest = $.ajax({
url: contentUrl,

// render the content or display error response

function renderContent(html) {
// insert the URL on the page at a div named 'returnedcontent'
// you can inject the HTML into the page however you like

function showErrorMessage(err) {
console.log('API Request Failure', err);

Example handlebars template
Link copied!

This is the example handlebars template (banner_slot_template) referenced from the URL. To use the code above, you  need to upload this to your account as an HTML file named "banner_slot_template".

{{#with bannerslot}}
<div id="contentRender"></div>
<div class="banner">
<div class="banner-editorial">
<div class="banner-header">{{headline}}</div>
<div class="banner-subheader">{{strapline}}</div>
<a class="banner-call-to-action" href="{{calltoactionurl}}"

HTML response
Link copied!

Here's an example HTML result. The image URL would include an image from your own account.

<div id="contentRender"></div>
<div class="banner">
<div class="banner-editorial">
<div class="banner-header">Winter collection</div>
<div class="banner-subheader">Stay warm. Stay stylish</div>
<!-- construct image URL from the data. Chose to default to HTTPS -->
src=" scarf"
<a class="banner-call-to-action" href="">Buy it now</a>

Custom parameters
Link copied!

Custom parameters can be added to the URL passed to the content rendering service. These parameters can then be referenced from within your handlebars templates, allowing you to implement different functionality based on variables such as locale or device, for example.

The params are included in the URL query parameters as follows:


With an example full URL for a content item:

The content rendering service includes a crParam namespace that contains the custom parameters. In the example above we are passing 'device' and 'account' parameters.

To access the custom parameters use the crParams helper, as shown below:

{{crParam 'device' .}}
{{#if (crParam 'device' .)}}

An example handlebars template that displays the result of a 'device' and 'account' custom parameter is shown below. You would access your own parameters from crParam as shown in the example.

<h1>Passed params template</h1>

Query string parameters can be passed to handlebars templates using the
crParam namespace:

{{#if (crParam 'account' .)}}
<h2>Passed param: account</h2>
<p>{{crParam 'account' .}}</p>
{{/if}} {{#if (crParam 'device' .)}}
<h2>Passed param: device</h2>
<p>{{crParam 'device' .}}</p>

Active end dates
Link copied!

If you use the Delivery API to retrieve a slot that is part of an edition with an active end date, then the edition expiry date is included in the JSON response.

If you want to access this information when using the content rendering service, then you can access edition expiry information in the HTTP headers returned in the response.

The headers are defined as follows.

X-Amp-Edition-Start-TimeThe edition start time
X-Amp-Edition-End-TimeThe edition end time
X-Amp-Edition-IDThe edition ID
X-Amp-Lifecycle-Expiry-TimeThe edition expiry time or null if the edition does not have an active end date

Contact your Customer Success Manager to have these headers enabled on your account.

Locale support
Link copied!

The content rendering supports thelocale parameter, so if a content item is localized, you can request the content in HTML format localized for a particular locale.

In the following example content with the ID 7b3a88ca-895a-4c24-b711-d2eec1563b83 is being requested for the fr-FR locale. This localized content is then converted to HTML format using the handlebars template named "content_template". You won't need to change any of your existing handlebars templates in order to process the localized content.

The French localized banner content will be returned in HTML format, as shown in the image below.

Localized content returned by the content rendering service

The locale parameter also makes use of the same locale filtering rules as the Delivery API. For more information see Locale filtering rules.

Handlebars documentation

Handlebars helpers GitHub repository

Active end dates

Creating localizable content types

Integrations that use the content rendering service
Link copied!

Salesforce Commerce Cloud integration

Salesforce Marketing Cloud integration

Dynamic Content to SAP connector