Dynamic Content
Learn how to use OneSignal Dynamic Content to personalize Push Notifications, SMS, and Emails at scale using CSV uploads and Liquid syntax.
Overview
Dynamic Content lets you personalize messages at scale—without creating separate versions for each audience. Whether you’re sending multi-language messages or tailoring content by region or campaign, Dynamic Content allows you to define one message that automatically adjusts for each user.
You do this by uploading a CSV file or programatically using our Template APIs with data containing content variations and referencing those values in your message using Liquid Syntax. When a message is sent, OneSignal pulls the appropriate content for each user based on their Data Tags.
Dynamic Content works across Push, Email, and SMS, making it ideal for:
- Multi-language onboarding or marketing flows
- Region or segment-specific promotions
- Personalization driven by external campaign data
Key benefits:
- Personalization at scale – Deliver custom experiences without creating and managing dozens of message variants.
- Multi-language support – Write one message that automatically displays in each user’s preferred language.
- Dynamic segmentation – Change message content based on user properties like language, region, plan, or custom tags such as campaign_id.
- Collaboration without friction – Let translators or non-technical teams create and edit message content directly in CSV files—no OneSignal login needed.
- Cross-channel compatibility – Use the same CSV logic across Push, Email, and SMS campaigns.
Common use cases:
- Event announcements per country or city
- Personalized push notifications based on campaign ID or purchase history
- Testing multiple subject lines or messages across user groups
See Message Personalization for more options on personalizing your messages.
Dynamic Content setup
Create a new message or template.
From the dashboard: Select Dynamic Content.
- Upload a CSV file that maps message content to Data Tags.
From the Templates APIs: Use the dynamic_content
property.
- Great solution if your dynamic content changes frequently.
Dynamic Content button found in the push create editor.
Format your content
You can start with a blank file or choose one of the provided templates:
- Multi-language
- Content personalization
CSV template options provided by OneSignal.
For API details, see:
CSV requirements
- File size must be under
200 KB
- Column headers:
- Alphanumeric only
- Use underscores (
_
) instead of spaces - Avoid special characters
- Ensure UTF-8 encoding in your spreadsheet editor
Map the subscription.language
property to different translations per section.
Similar to a VLOOKUP formula in Excel, we match user attributes with the corresponding content from the CSV.
Map the subscription.language
property to different translations per section.
Similar to a VLOOKUP formula in Excel, we match user attributes with the corresponding content from the CSV.
Use a tag like campaign_id
to dynamically render content for that user.
Example personalization based on tags.
Important: Remove spaces and non-alphanumeric characters from CSV headers or use hash notation in Liquid.
Example shows a more detailed CSV using additional liquid syntax to reference the user's tag.
Once complete, upload the file.
The Upload CSV step in the dashboard.
Example showing a fully uploaded CSV. Press Close and continue.
Reference Dynamic Content in messages
To display personalized content, use this Liquid syntax based on if you used a CSV or the dynamic_content
property.
Replace:
file_name
: CSV file name (without.csv
), omit if using thedynamic_content
propertysection_name
: Value in the first column of the row or propertyuser_property
: Column header or property matching a Data Tag
Notation examples
Multi-language:
Campaign ID:
In this example, campaign_id
is a Data Tag.
Add fallback content
To ensure your message renders even if a user lacks a tag or property, you can use:
Fallback column in CSV
Include a default
value in the liquid syntax to display data in a column if the user doesn’t have the property or tag.
Hard-coded fallback (if/else)
Examples
Multi-language email
Use translations.csv
to localize your email:
{{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.
Update subject lines, preheaders, button labels, and URLs using Liquid.
Personalized push message
Use content_personalization_template.csv
for user-specific push messages:
{{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
Create a test CSV
Multi-language test:
- Columns:
email
,language
Personalization test:
- Columns:
external_id
,campaign_id
Example CSV to upload and create segment of email testers.
Use +
addressing in emails to test multiple variations: username+test@example.com
Example CSV to upload and create segment of testers with external_id and the tag campaign_id.
Upload your test segment
Go to Subscriptions or Segments > Upload/Import Users.
Set the first column as the identifier. All other columns are treated as user properties or Data Tags.
Create a segment of your testers to repeat as needed.
See Import for more on uploading user data.
View the message
After sending your test messages, check your inboxes or devices to verify display.
Example shows the email sent with Dynamic Content.
Example shows the push sent with Dynamic Content.
You can now scale personalized messaging using these templates and CSVs.
Usage considerations
When to use Dynamic Content vs. Custom Data
- Use Dynamic Content for diverse languages or personalized message blocks.
- Use Custom Data for simple, inline personalization in a single language.
Editing templates
Re-upload CSVs or use the dynamic_content
property of the Update Template API to update.
Special characters in keys
Use hash notation if keys contain non-alphanumeric characters:
Use dot notation for standard alphanumeric keys: