Iterable integration
This guide walks you through connecting an Iterable project to Better Email and syncing your Campaigns into it as email templates. It also covers the optional parts: letting Better Email create the Iterable campaign, language versions, Segments, and syncing user profile fields as recipient fields.
Before you start
To set up the Iterable integration, you will need:
- An Iterable project where you can create API keys and see Settings → Senders
- An admin user in Better Email who can create and edit integrations
1. Create a server-side API key in Iterable
- In Iterable, go to Integrations → API keys.
- Click New API key.
- Give it a name such as
Better Email, choose the Server-side type, and create it. - Copy the key.
The key has to be server-side. Iterable's other key types can't write templates, and Better Email tells you so when it tries. A server-side key can also send campaigns and read user profiles, so make one for Better Email alone rather than reusing a key another system holds.
2. Save and enable the integration in Better Email
- Go to Integrations in Better Email.
- Create a new integration or open an existing one.
- Choose Iterable as the type and give it a clear name.
- Paste the key into API key.
- Pick the Data center. Choose EU if your team signs in at
app.eu.iterable.com, otherwise US. A key only works against its own data center, so a wrong pick shows up as a rejected key. - Check Enabled and click Save.
One integration is one Iterable project. If you work in several projects, create one integration per project.
3. Set up a Destination
Saving creates the integration's default Destination. A Destination is a sending identity inside the project, and it goes on every template exported through it. Open the Destinations tab and fill in:
| Setting | What it does |
|---|---|
| From name and From email | The sender on the template. The address must be listed under Settings → Senders in the Iterable project, or Iterable refuses the export. Left blank, the template keeps whatever Iterable has. |
| Reply-to email | Optional. |
| Message type | Click Fetch from Iterable and pick one of the project's email message types. Each is labelled with its channel, Marketing or Transactional. Leave it on Project default to let Iterable decide. |
The message type matters for one reason. Iterable requires every email on a marketing message type to carry one of its own unsubscribe links, so the Design System's unsubscribe link has to point at {{unsubscribeUrl}} (or {{hostedUnsubscribeUrl}} or {{unsubscribeMessageTypeUrl}}), unless the project has Iterable's Auto-append Unsubscribe Block turned on, which adds one itself. A Destination with a transactional message type has no such requirement.
If you send under several senders or message types, add one Destination per combination. Campaigns pick their Destination when they are created.
4. Export to Iterable
On the Campaign's Review tab, click Sync to <your Iterable integration>.
- The first sync creates an email template in Iterable, named after the Campaign, with its subject, preheader, HTML and the Destination's sender and message type.
- Later syncs update that same template by its id, so there is one template per Campaign no matter how often you sync.
- After a sync the Review tab shows an Open in Iterable link to the template, or to the campaign when Better Email created one.
- Merge tags and Segments are written in Iterable's Handlebars. See Segments and merge tags.
Iterable requires a subject line, so a Campaign without one is refused before anything is written. Add the subject and sync again.
Iterable adds its own hidden preheader to the top of the email from the template's preheader field. If your Design System already renders a hidden preheader, Better Email leaves Iterable's field empty, so the preheader doesn't appear twice in the inbox.
What Iterable does to the HTML at send time
Iterable doesn't inline CSS, so your <style> block arrives as you wrote it. It does minify the HTML when it sends: colours are shortened, whitespace between tags is collapsed. Comments, Outlook conditional comments, dark-mode media queries and the contents of <pre> tags survive. Links are rewrapped for click tracking.
5. Optional: let Better Email create the campaign
By default an export stops at the template, and someone in Iterable builds the campaign from it. Iterable copies the template into the campaign at that point, so a later sync updates the template but not the campaign.
Turning on campaign creation skips that round trip. Open the integration, turn on Create the campaign in Iterable, and save.
Choosing the list
With campaign creation on, the sync dialog shows a Campaign list picker with the project's standard and dynamic lists. Pick who the campaign sends to and sync. You can still change the list in Iterable before sending.
How it behaves
- The first sync creates a blast campaign in Iterable, named after the Campaign, on the list you picked, in the Ready state. Better Email also adds the project's global suppression lists, which Iterable doesn't add to campaigns made through its API. Nothing is scheduled or sent.
- Later syncs push the new version into the campaign as well as the template, for as long as the campaign is a draft or Ready.
- Once the campaign is scheduled or sending, Better Email refuses to change it. The sync fails with "Cancel it in Iterable, then sync again", because the alternative is letting the old content go out. Cancelling a scheduled campaign in Iterable puts it back to Ready.
- A finished campaign is left alone. The template is updated; the campaign that already went out is history.
Scheduling, sending, A/B tests and anything else about the campaign happen in Iterable. Better Email never schedules or sends.
Export as a new copy
The sync dialog has an In Iterable choice with two options:
- Update the linked template is the default and does what the sections above describe.
- Export as a new copy creates a new template, and a new campaign when campaign creation is on. The Campaign links to the new ones from then on and the old ones stay as they are. Use it when a campaign in Iterable has already gone out and you want to send a changed version.
Language versions can't be exported as a new copy, because they share one template.
6. Language versions
The language versions of a Campaign share one Iterable template, one locale each. Syncing any version writes its content into the template under that version's locale, so one Iterable campaign reaches every language, which is how Iterable's own localization works.
Two things to set up:
- The locale must exist in Iterable. Every locale code Better Email writes has to be configured under Project Settings → Locales in the project. Iterable refuses a locale it doesn't know and names the ones it does.
- Locale codes on the integration maps a Campaign language to the code the project uses, when they differ. Write one mapping per language, comma separated, for example
da=da-DK, fr=fr-CA. Unmapped languages use the Campaign's language as is.
Iterable stores the sender per locale, so Better Email writes the Destination's sender into every locale it syncs. A Campaign outside a translation group writes into the template's default locale.
Adding languages after the master has been synced works the same way: the new versions add their locales to the master's template and campaign.
What happens to recipients whose locale the template doesn't have depends on the project's locale preferences in Iterable: it either sends them the default locale or skips them. Check which one your project uses, and sync every language version before sending.
To send the language versions again after the campaign has gone out, sync them, then create a new campaign in Iterable from the synced template, which has every locale. Don't duplicate the old campaign: it keeps its own copy of the template as it was when it was sent. Export as a new copy isn't available for language versions, since it would split them into separate templates.
7. Segments and merge tags
Recipient fields inserted in the Campaign Editor export as Handlebars, {{field}}, which Iterable fills per recipient at send time. Segments export as {{#if}} blocks around the content they apply to, using Iterable's comparison helpers. Groups with and, or and not work, nested as deep as you need.
Number and date conditions are written so a recipient with a missing or oddly typed field never stops the send. In plain Handlebars a greater-than on a missing field fails the whole template; Better Email avoids that:
- A missing number counts as 0, and a whole number and its decimal form (
12and12.0) compare equal. - A missing date matches neither "before" nor "after" a given day.
Iterable checks a condition's syntax when the template is saved, so a Segment it can't parse fails the sync. Values are only filled in at send time: a recipient whose data a condition still can't handle is skipped for that send, not the whole campaign.
8. Optional: sync recipient fields from Iterable
- On the integration, turn on
Sync recipient fieldsand save. - Click
Sync nowin the page header.
Better Email reads the project's user profile fields and creates one recipient field per field, keeping text, number, yes/no and date types. Iterable's own bookkeeping fields are left out: device records, phone number details, subscription and list memberships, and profile timestamps. Fields Iterable types as objects or arrays are left out too.
Performance data
Better Email can show how your Iterable campaigns performed: sends, deliveries, bounces, opens, clicks, unsubscribes and spam complaints. It also shows whether the campaign Better Email created is scheduled or has been sent. See Performance data from Iterable.
Troubleshooting
| Symptom | Fix |
|---|---|
| "Iterable rejected the API key" | The key isn't a server-side key, or the integration's Data center doesn't match the project. Check both. |
| "Iterable needs a verified sender before it accepts email templates" | The project has no sender yet. Add one under Settings → Senders in Iterable, then sync again. |
| "Iterable refused the from email" | The Destination's From email isn't in the project's Senders list. Add it there, or change the Destination. |
| "Iterable needs a subject line" | Add a subject to the Campaign and sync again. |
| "Iterable needs an unsubscribe link in marketing emails" | The Destination uses a marketing message type and the HTML has no {{unsubscribeUrl}}. Point the Design System's unsubscribe link at it and sync again. Don't switch to a transactional message type to get around it: transactional messages ignore marketing opt-outs. |
| "Locale 'xx' is not supported for this project" | Add the locale under Project Settings → Locales in Iterable, or map the language under Locale codes on the integration. |
| "The Iterable campaign is scheduled, so the new version was not applied" | Cancel the campaign in Iterable, which puts it back to Ready, then sync again. |
| "Choose the Iterable list the campaign sends to" | Campaign creation is on and no list was picked. Pick one in the Campaign list field of the sync dialog. |
| "The chosen Iterable list no longer exists" | The list was deleted in Iterable. Pick another in the sync dialog. |
| "Language versions share one Iterable template, so they cannot be exported as a new copy" | Export the group with Update the linked template, or duplicate the Campaign instead. |
| The email sends but never arrives | The sender is in Iterable's Senders list but its address or domain isn't verified for sending. Iterable finishes the campaign but records those recipients as skipped, not sent. Check the sender's verification in Iterable. |