Dynamic Content
OneSignal Reusable Push Notification, SMS, and Email Templates
Dynamic Content allows you to create a single email, SMS, or push notification that is dynamically personalized for each recipient. Using Liquid Syntax, you can upload a CSV file containing personalized content and configure your message to automatically extract and display relevant data based on recipient attributes.
This feature opens up new avenues for personalized, efficient, and language-sensitive communication, allowing businesses to enhance engagement with diverse customer segments.
Key Benefits:
- Ideal for Multi-Language Communication – Manage and send multilingual content effortlessly, making it easy to reach a global audience. Dynamic Content is ideal for sending with many languages at once.
- Segment-Specific Content – Send a single message tailored to multiple segments, ensuring each recipient receives content relevant to their interests or behaviors.
- No Direct Access Needed for Content Editors – Content editors can create personalized messages without needing direct access to OneSignal, streamlining workflows when collaborating with domain experts or translators.
Common use cases include translation/localization, personalized content based on user preferences, and customized messaging based on a user's country or location.
Dynamic Content setup
Start by creating a new message or Template.
Select the Dynamic Content button within the Email, Push, and SMS create form. This works for any type of editor applicable for that channel.

Dynamic Content button found in the push create editor.
You will see instructions on how to upload personalized content. Adding Dynamic Content to a message requires a CSV file containing the content to be displayed according to your recipient's User properties or Data Tags.
Format a CSV
You can either start from scratch or select start from a template. We provide two example templates to help you get started: Multi-language and Content Personalization.
You can download the example template and open in a spreadsheet editor. Ensure your editor is set to load and save files in UTF-8 encoding.

CSV template options provided by OneSignal.
The first row of the CSV contains column names, which act as keys for user properties or data tags referenced in the message.
In the example below, the user.language
property is mapped to the language_code in each column. The first column is intentionally left blank, allowing you to reference different sections of the message—especially useful for email formatting.
Think of this as similar to a VLOOKUP formula in Excel, where the system matches user attributes with the corresponding content from the CSV.

Example of the multi-language csv template.
Here is another example that shows setting a Data Tag called campaign_id
and referencing it to display content to different users based on the tag.

Example personalization based on data tags.
Each subsequent row corresponds to a section of the message, with content that will be injected dynamically based on the specified identifier in the first column.

Example will show the translated message in each section we specify in the message.

Example will show the dynamic content based on each user's campaign_id
tag.
Make sure each row is given a unique identifier and ensure it does not include spaces or unique characters. If you reference data tag keys with spaces, you will need to update the tag to remove the spaces in the key.
The CSV can also contain other more personalization Using Liquid Syntax if desired.

Example shows a more detailed CSV using additional liquid syntax to reference the user's name
tag.
When ready, upload the template to your message.

The Upload CSV step in the dashboard.
Press Close once the CSV is uploaded.

Example showing a fully uploaded CSV. Press Close and continue.
Reference your uploaded Dynamic Content in a message
To inject the data from the CSV to display properly in your message, you must substitute and reference the columns and rows within the CSV Using Liquid Syntax. The format of the liquid syntax is as follows.
{{dynamic_content.file_name.section_name[user_property]}}
Substitute the values in the provided liquid with the values you uploaded, so the message populates your user's custom data at email send time. Replace these values:
file_name
: The filename of the CSV without the .csv filetype.section_name
: The value of the first column with row data you want to display.[user_property]
: The column associated with the user property you want to display.
In the multi-language example, the CSV is named translations.csv
so we convert {{dynamic_content.file_name.section_name[user_property]}}
to {{dynamic_content.translations.section_1[user.language]}}
.
In the content personalization example, the CSV is named content_personalization_template.csv
so we convert {{dynamic_content.file_name.section_name[user_property]}}
to {{dynamic_content.content_personalization_template[campaign_id].title}}
.
Add a fallback property to your message
When substituting content, there's always a chance that a subscription is missing a value for a Data Tag, or does not have a language set. In that case, you could specify a fallback property.
There are two ways to define defaults in Using Liquid Syntax that apply in this case
1. Setting a variable at the top of your message
This is the recommended option for emails or content with multiple substitutions.
{% assign lang = user.language | default: "en" %}
~~~
{{dynamic_content.translations.section_1[lang]}}
{% assign campaign_id = campaign_id | default: "21234086613" %}
~~~
{{dynamic_content.content_personalization_template[campaign_id].title}}
2. Referencing the default value specifically for each substitution.
{{dynamic_content.translations.section_1[user.language] | default: dynamic_content.translations.section_1.en}}
{{dynamic_content.content_personalization_template[campaign_id].title | default: dynamic_content.content_personalization_template.21234086613.title}}
Example of Dynamic Content for a multi-language email
Using the translations.csv
example for a multi-language email, your email message template will include a section_1
and section_2
referring to the content of the row for each user.language
property in the associated column to display according to the User's language code.
Build out the design of your email and substitute all text that needs to be rendered from your dynamic content. Once you replace the boilerplate liquid syntax with your CSV file and dynamic content properties, your liquid syntax should be like the examples below. Please note these examples refer to the CSV example shown above.
{{dynamic_content.translations.section_1[user.language]}}
{{dynamic_content.translations.section_2[user.language]}}

Example shows how to add the liquid syntax for the multi-language example.
Note that you can update all aspects of the email from the Subject line, Preheader text, button text, URLs, and even swap out the unsubscribe language, by editing the "Text to display".
Example of Dynamic Content for a personalized push
Using the content_personalization_template.csv
example for a personalized push, your push message template will include a campaign_id
referring to the tag set on each user and the content in the row for each message property column.
Build out the design of your push and substitute all text that needs to be rendered from your dynamic content. Once you replace the boilerplate liquid syntax with your CSV file and dynamic content properties, your liquid syntax should be like the examples below. Please note these examples refer to the CSV example shown above.
{{dynamic_content.content_personalization_template[campaign_id].title}}
{{dynamic_content.content_personalization_template[campaign_id].message}}
{{dynamic_content.content_personalization_template[campaign_id].url}}

Example shows how to add the liquid syntax for the content personalization example.
Test and preview
To view your message and how it will be sent to your customers, you'll want to set up a segment of test users and send out a message to that segment.
Create a CSV of test users
Create the CSV file of test recipients, and add at minimum of:
email
andlanguage
for testing the multi-language email example.external_id
andcampaign_id
tag for testing the content personalization example.

Example CSV to upload and create segment of email testers.
Make sure the language follows the language_code format.
Note on test emails
Most inboxes allow you to add a
+
then a value, to send a different email to the same inbox. username+test@example.com format is used to create many test users that will send the different test emails to the same inbox.

Example CSV to upload and create segment of testers with external_id and the tag campaign_id.
Upload your test segment
To upload your test segment, go to the Subscriptions or Segments page and select Upload/Import Users
Note: The identifier should be the first column. Any column after the first is treated as a user property or data tag that will be added or updated for that identifier.
After adding the file to the CSV import tool, you can create a segment during the import process. Select "Create Segment" to generate a recipient list and choose your target audience for the message.

Create a segment of your testers to repeat as needed.
CSV Upload Details.
See Import for more details on importing CSVs of user data.
View the rendered message
After you have sent the messages to your test segment, check each device to see how it looks!

Example shows the email sent with Dynamic Content.

Example shows the push sent with Dynamic Content.
Dynamic Content Tutorial Completed!
You can now adjust your message templates and CSVs as needed to send at scale to your users.
Usage Considerations
When to Use Dynamic Content vs. Custom Data
- Use Dynamic Data when composing messages that encompass diverse languages or varied content types tailored to user-specific data
- Custom Data can be used when aiming to personalize specific data elements within a message in a single language
Size Limits for Dynamic Content
- The size limit for dynamic content is 200kb
Updating and Editing Templates
- To replace values in a template, you can download the CSV you imported into the Dynamic Content drawer and re-upload to make changes.
- The content is disconnected when you make a campaign from a template or save a template from a campaign. Editing the new CSV won't edit the old one.
Handling Non-Alphanumeric Characters
When your CSV contains non-alphanumeric characters in section names or user properties, you should use hash notation versus alphanumeric and dot notation to display their values in Liquid syntax.
For example, using Hash notation with non-alphanumeric characters.
Hash Notation: {{ dynamic_content.file_name["!the_row!"]["&the_column&"] }}
However, for section names and properties with alphanumeric characters, use dot notation:
Dot Notation: {{ dynamic_content.file_name.the_row.the_column }}
Updated 11 days ago