---
canonical: https://amplience.com/developers/docs/apis/content-rendering-service/
title: The content rendering service
description: The Amplience content rendering service automates combining JSON content with handlebars templates to generate HTML that can be added to a page on your website.
audience: Developer
image: https://cdn.media.amplience.net/i/ampproduct/content-rendering-with-locales-2?w=1200&h=630
image_width: 1200
image_height: 630
date_published: 2022-07-12
date_modified: 2025-06-23
---

# 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 v2 overview](https://amplience.com/developers/docs/apis/content-delivery/content-delivery-overview) page.

The [Salesforce Commerce Cloud](https://amplience.com/developers/docs/integrations/commerce/salesforce/slots/) and [Salesforce Marketing Cloud](https://amplience.com/developers/docs/integrations/marketing/salesforce-marketing-cloud/) integrations make use of the content rendering service. It's also used in the [Dynamic Content to SAP connector](https://amplience.com/blog/introducing-the-sap-connector/).

## Using the content rendering service

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

```
/v1/content/:store/content-item/:id?template=:name
```

### Example

```
https://cdn.c1.amplience.net/v1/content/ampproduct/content-item/cea10270-7c3f-44b8-88d3-475956d2a901?template=content_template
```

### Parameters

| Parameter | Description                                                                                                              |
| --------- | ------------------------------------------------------------------------------------------------------------------------ |
| store     | Replace this with your company tag. You can find this by looking at the dynamic URL of an asset published in Content Hub |
| id        | The unique content ID for a piece of content included in your account                                                    |
| template  | The name of a handlebars template. This must be uploaded to your account as a text or HTML file                          |

### Status codes

| Status code | Description                                                       | Response                            |
| ----------- | ----------------------------------------------------------------- | ----------------------------------- |
| 200         | OK. Content was found, template was found and HTML was generated  | HTML                                |
| 400         | Bad Request. Empty store / id or template name field              | Plain text                          |
| 404         | Not Found. Could not find the template provided                   | Plain text                          |
| 404         | Referenced partial template not found                             | Plain text                          |
| 500         | Server Error. Recursive template / Maximum template depth reached | Plain text                          |
| 500         | Server Error. Recursive content graph                             | Plain text                          |
| 500         | Server Error. Handlebars processing errors                        | Plain text handlebars error message |
| 500         | Server Error. Crashes of any kind                                 | Plain text                          |

### Notes

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 `cdn.c1.amplience.net` with the domain of a virtual staging environment, for example, if the staging domain is `1vkz2i2i1hlau19hndnr03duvb.staging.bigcontent.io` then the URL would be as follows:

```html
https://1vkz2i2i1hlau19hndnr03duvb.staging.bigcontent.io/v1/content/store/content-item/cea10270-7c3f-44b8-88d3-475956d2a901?template=content_template
```

## Handlebars

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

We have included most of the helpers defined in the handlebars helpers [GitHub repository](https://github.com/helpers/handlebars-helpers) 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

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.

```handlebars
{{#markdown blogtext}}{{/markdown}}
```

If the blogtext property contained the following markdown:

```markdown
# This is heading 1

## This is heading 2

### This is heading 3
```

it would be converted into the following HTML:

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

### Handlebars templates

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'.

```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>
  </div>
  <img
    class="banner-background-image"
    src="https://{{background.defaultHost}}/i/{{background.endpoint}}/{{background.name}}"
  />
  <a class="banner-call-to-action" href="{{calltoactionurl}}"
    >{{calltoactiontext}}</a
  >
</div>
{{/with}}
```

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

```
https://cdn.c1.amplience.net/v1/content/ampproduct/content-item/7ba216e9-7db2-41fa-ba0b-e1833f162be0?template=banner_slot_template
```

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.

### Partials

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:

```html
{{#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.

```
https://cdn.c1.amplience.net/v1/content/ampproduct/content-item/cea10270-7c3f-44b8-88d3-475956d2a901?template=top_template
```

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

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

We currently use the following handlebars versions:

- handlebars: 4.7.7
- handlebars-helpers: 0.9.8

### Limitations

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.

> **Note: Inline partials**
> Currently [inline partials](https://handlebarsjs.com/guide/partials.html#inline-partials) are not supported.

## Using the content rendering service example

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

> **Info:** 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

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.

```javascript
// '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 =
  'https://cdn.c1.amplience.net/v1/content/ampproduct/content-item/' +
  slotID +
  '?template=banner_slot_template';

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

// render the content or display error response
deliveryRequest.success(renderContent).fail(showErrorMessage);

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
  $('#returnedcontent').html(html);
}

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

### Example handlebars template

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".

```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>
  </div>
  <img
    class="banner-background-image"
    src="https://{{background.defaultHost}}/i/{{background.endpoint}}/{{background.name}}"
  />
  <a class="banner-call-to-action" href="{{calltoactionurl}}"
    >{{calltoactiontext}}</a
  >
</div>
{{/with}}
```

### HTML response

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

```html
<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>
  </div>
  <!-- construct image URL from the data. Chose to default to HTTPS -->
  <img
    class="banner-background-image"
    src="https://cdn.media.amplience.net/i/store/winter scarf"
  />
  <a class="banner-call-to-action" href="www.google.com">Buy it now</a>
</div>
```

## Custom parameters

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:

```
?crparam.device=kiosk&crparam.account=amplience
```

With an example full URL for a content item:

```
https://cdn.c1.amplience.net/v1/content/ampproduct/content-item/07be26bb-bc37-4ade-97f9-1ba8979f4cba?template=example_params&crparam.device=kiosk&crparam.account=amplience

```

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.

```html
<h1>Passed params template</h1>

<p>
  Query string parameters can be passed to handlebars templates using the
  crParam namespace:
</p>
<p><code>?crparam.device=kiosk&crparam.account=amplience</code></p>

{{#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>
{{/if}}
```

## Active end dates

If you use the Delivery API to retrieve a slot that is part of an edition with an [active end date](https://amplience.com/developers/docs/dev-tools/guides-tutorials/slots), 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.

| Parameter                   | Description                                                                     |
| --------------------------- | ------------------------------------------------------------------------------- |
| X-Amp-Edition-Start-Time    | The edition start time                                                          |
| X-Amp-Edition-End-Time      | The edition end time                                                            |
| X-Amp-Edition-ID            | The edition ID                                                                  |
| X-Amp-Lifecycle-Expiry-Time | The 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

The content rendering supports the`locale` parameter, so if a content item is [localized](https://amplience.com/developers/docs/dev-tools/guides-tutorials/localization), 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.

```html
https://cdn.c1.amplience.net/v1/content/ampproduct/content-item/7b3a88ca-895a-4c24-b711-d2eec1563b83?template=content_template&locale=fr-FR
```

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](https://cdn.media.amplience.net/i/ampproduct/content-rendering-with-locales-2?w=1880&fmt=png '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](https://amplience.com/developers/docs/dev-tools/guides-tutorials/localization#locale-filtering-rules).

## Related Pages

[Handlebars documentation](http://handlebarsjs.com)

[Handlebars helpers GitHub repository](https://github.com/helpers/handlebars-helpers)

[Active end dates](https://amplience.com/developers/docs/dev-tools/guides-tutorials/slots)

[Creating localizable content types](https://amplience.com/developers/docs/dev-tools/guides-tutorials/localization)

### Integrations that use the content rendering service

[Salesforce Commerce Cloud integration](https://amplience.com/developers/docs/integrations/commerce/salesforce/slots/)

[Salesforce Marketing Cloud integration](https://amplience.com/developers/docs/integrations/marketing/salesforce-marketing-cloud)

[Dynamic Content to SAP connector](https://amplience.com/blog/introducing-the-sap-connector/)
