To help your users manage their subscription preferences, you can build a custom subscription preference center and link to it from messages sent from Iterable. This is a perfect way to let users set personal preferences for all of your brand's communication channels in one place.
This guide describes how to use Iterable's API to integrate a custom subscription preference center.
NOTE
Push Planet offers a subscription preference center solution that's integrated with Iterable, designed for marketers, and requires no software development. It can be added to your existing Iterable contract for easy billing. If you're interested, contact your customer success manager.
# In this article
- Overview
- Implementing a subscription preference center
- Step 1: Set up message channels and types
- Step 2: Build a subscription preference center
- Step 3: Add your project's hosted unsubscribe URL
- Step 4: Use the hosted unsubscribe URL for List-Unsubscribe (optional)
- Step 5: Use the hosted unsubscribe URL in templates
- Attributing unsubscribes to a specific campaign and template
# Overview
Managing subscription preferences is a critical part of maintaining a positive relationship with your users. Iterable provides flexible tools to help you manage subscription preferences, including:
- Default subscription pages - Iterable hosts these pages for you. They are branded with your project's name and logo.
- APIs that fetch and update subscription preferences. You can use these APIs to build a custom subscription preference center on your website or app and integrate it with Iterable.
# Using Iterable's default subscription pages
When you're not using a custom preference center, Iterable generates default unsubscribe pages similar to those shown below. To create these pages, Iterable uses your project's name and logo and the name of the relevant message channel or message type. You can update these values in the Settings > Project Settings screen.
-
When users click
{{unsubscribeUrl}}
links, the success message displays the name of the channel from which they have unsubscribed: When users click
{{unsubscribeMessageTypeUrl}}
links, the success message displays the name of the message type from which they have unsubscribed.-
When users who are currently unsubscribed click
{{unsubscribeUrl}}
links,{{unsubscribeMessageTypeUrl}}
links, or click the "Resubcribe" button on the default unsubscribe page, the success message displays the name of the channel or message type to which they've resubscribed.
# Using a subscription preference center
A subscription preference center is a page in your website or app where users can manage their subscription preferences for marketing messages. This includes:
- Opting in or out of specific message types, channels, and lists.
- Updating their email address or other personal contact information.
A subscription preference center is a valuable tool for maintaining a positive relationship with your users. It allows them to control the messages they receive, which can help reduce unsubscribes and complaints.
# Implementing a subscription preference center
To implement a subscription preference center, your team needs to do the following:
- Set up message channels and types in Iterable.
- Build a subscription preference center on your website or app.
- Add your preference center's URL to Iterable (hosted unsubscribe URL).
- Set up the hosted unsubscribe URL for easy unsubscribe (optional).
- Add the hosted unsubscribe URL in templates.
Keep reading for detailed instructions on each step.
# Key features of a subscription preference center
A successful subscription preference center should:
- Display a user's current subscription preferences.
- Allow users to update their subscription preferences.
- Use Iterable's APIs to fetch and update subscription preferences.
- Be accessible from a link in your marketing messages.
# Important reminders for security and compliance
When you create a custom subscription preference center, here are two important reminders related to compliance, security, and user experience:
# Stay compliant with sender requirements
When you use a custom preference center, you are responsible for managing unsubscribe requests and updating user preferences in Iterable in a timely manner.
Iterable does not automatically unsubscribe users who click on a hosted unsubscribe URL. Instead, your server must handle requests to change preferences by making API calls to Iterable.
IMPORTANT
Failure to process unsubscribe requests and continuing to send messages after a user indicates their request to unsubscribe can result in:
- Harm to your brand's reputation.
- Spam complaints.
- Serious deliverability and compliance concerns for regulated messaging channels like email and SMS.
- Violation of Iterable policies, such as acceptable use and anti-spam.
# Make API calls from your server, not the browser
When you build a custom subscription preference center, use your server to make API calls that fetch and modify a user's subscription preferences. This is important for security reasons, as it prevents client-side JavaScript from accessing your server-side API key.
WARNING
The APIs that fetch and update a user's subscription preferences require authentication with a server-side API key. This type of API key can access all of your project's data, so it's never safe to embed a server-side API key in client-side code (whether JavaScript, a mobile app, or otherwise). Instead, make API calls from your server. Then, use the data returned from those calls to display a web page that has no knowledge of the API key.
# Step 1: Set up message channels and types
First, set up your project's message channels and types.
It's common to set up a single marketing channel per message medium (email, push, SMS, etc.) and specific message types within each of those channels. For some more tips, read Message Channels and Types Best Practices.
# Step 2: Build a subscription preference center
A subscription preference center should allow users to view and update their subscription preferences.
For example, this screenshot shows a subscription preference center that allows users to manage their subscriptions for various types of marketing emails:
# 2.1 Displaying a user's subscription preferences
When rendering a subscription preference center, your web server should populate the screen with data about a specific user's subscription preferences. To determine which user's data to display, use a URL parameter as described below).
Your web server can retrieve the user's current subscription preferences by
calling Iterable's GET /api/users/{email}
or GET /api/users/byUserId/{userId}
APIs (depending on your project's unique identifier).
When you are finished with this step, your subscription preference center should display the user's current subscription preferences when the page loads.
For example, consider the following subscription preferences:
To represent this data, the response from GET /api/users/{email}
might look similar to the following:
{ "user": { "email": "user@example.com", "dataFields": { "emailListIds": [5, 6, 7], "unsubscribedMessageTypeIds": [1, 2] } } }
This data indicates that the user is unsubscribed from message types 1
and
2
, which in this example correspond to Daily Promotional
and Weekly Promotional
marketing emails.
NOTE
Response bodies include the emailListIds
or userListIds
(depending on the
project type), unsubscribedChannelIds
, unsubscribedMessageTypeIds
, and
subscribedMessageTypeIds
arrays only if any one of those values has been
modified for the user in question. This applies to these APIs:
GET /api/users/{email}
GET /api/users/getByEmail
GET /api/users/byUserId/{userId}
GET /api/users/byUserId
Message types with an opt-out subscription policy, for example, won't reflect in this list unless the user has changed their preference.
# 2.2 Updating a user's subscription preferences
The above user might update their subscription preferences as follows:
When the user submits these updates, your web server should pass them to the
POST /api/users/updateSubscriptions
API, with a request body similar to the following:
{ "email": "user@example.com", "unsubscribedMessageTypeIds": [2, 4] }
In this example, if the user selected Unsubscribe Me From All Marketing Emails, the request body might instead look something like this:
{ "email": "user@example.com", "unsubscribedChannelIds": [100], "unsubscribedMessageTypeIds": [1, 2, 3, 4, 5] }
This request body unsubscribes the user from the channel and the individual message types.
If you're subscribing a user to a double opt-in message type (SMS only), use the
POST /api/subscriptions/subscribeToDoubleOptIn
endpoint to trigger the SMS Double Opt-In
subscription flow.
# Using the Subscriptions API and opt-in message types
NOTE
Iterable's Subscriptions API and opt-in message types are enabled by default for all organizations created after September 2019.
Because of a breaking API change, organizations created before September 2019 don't have Iterable's Subscriptions API or opt-in message types enabled by default. If your organization was created before this date, your customer success manager must enable this feature.
To learn more about the impact of this update, read Breaking API Change.
If your account or project has enabled opt-in message types, you can also use the following APIs to modify user subscriptions to message channels, message types and lists:
PATCH /api/subscriptions/{subscriptionGroup}/{subscriptionGroupId}/user/{userEmail}
DELETE /api/subscriptions/{subscriptionGroup}/{subscriptionGroupId}/user/{userEmail}
PUT /api/subscriptions/{subscriptionGroup}/{subscriptionGroupId}?action=subscribe
PUT /api/subscriptions/{subscriptionGroup}/{subscriptionGroupId}?action=unsubscribe
# Updating SMS Double Opt-In preferences
Double opt-in is a message type that triggers a SMS double opt-in flow that sends users a SMS to confirm their request. Users must reply to subscribe to these message types.
To include a SMS double opt-in message type in your preference center, use the
POST /api/subscriptions/subscribeToDoubleOptIn
endpoint to trigger the SMS Double Opt-In subscription flow.
To learn more, read SMS Double Opt-In Overview.
# Step 3: Add your project's hosted unsubscribe URL
The hosted unsubscribe URL is the link that directs users to your custom
subscription preference center. Iterable serves this URL in email templates
with the {{hostedUnsubscribeUrl}}
merge parameter.
Go to Settings > Project Settings and find the Hosted Unsubscribe URL setting.
Enter the URL for your preference center. You may wish to include parameters
like email
or userId
to identify the user.
# Using parameters to pass data in your hosted unsubscribe URL
When you enter your hosted unsubscribe URL in the Hosted Unsubscribe URL field, you can use parameters and Handlebars to pass additional data to your preference center.
To use the hosted unsubscribe URL for easy unsubscribe,
the URL must include merge parameters for either email
or userId
to
identify the user (depending on how your project identifies users).
Some Iterable project types do not support cookies, so you may need to pass
the user identifier as a URL parameter. To identify the user, you can add a URL
parameter for your project's unique identifier, email
or userId
. You should
URL-encode the user identifier's value with the #urlEncode
Handlebars helper.
Example:
https://www.example.com/accounts/preferences?email={{#urlEncode}}{{email}}{{/urlEncode}}
# Step 4: Use the hosted unsubscribe URL for List-Unsubscribe (optional)
Next, decide whether to use the hosted unsubscribe URL as the
List-Unsubscribe
email header, which uses the preference center's URL for
easy unsubscribe.
This is optional and requires additional setup.
Iterable automatically uses the default unsubscribe URL for the
List-Unsubscribe
header, even if you have a hosted unsubscribe URL set up.
Clicks made on default easy unsubscribe links are processed by Iterable's
default unsubscribe process, and users are unsubscribed from the message
channel that the campaign was sent from.
When you use a hosted unsubscribe URL for easy unsubscribe, the following considerations apply:
HTTPS is required. URLs that use HTTP are not supported.
Iterable does not automatically unsubscribe users when they click on the easy unsubscribe link. Instead, your server must handle the
POST
request for easy unsubscribe and promptly process opt-outs in a one-click experience.Iterable does not track any events until your server sends an API request to Iterable. This means that users are not unsubscribed until your server processes the
POST
request and sends the data back to Iterable, and that Iterable does not track a hosted unsubscribe click event when using this URL for easy unsubscribe.
To set up your hosted unsubscribe URL for easy unsubscribe, follow these steps:
- Update your web server to handle the
POST
request for easy unsubscribe. - Update your project settings to use the hosted unsubscribe URL for List-Unsubscribe headers.
- Contact Iterable to enable the hosted unsubscribe URL for List-Unsubscribe. Your customer success manager or Iterable Support can help with this.
- Test the hosted unsubscribe URL for easy unsubscribe.
Continue reading the next sections for detailed instructions.
# 4.1 Handle the POST request for easy unsubscribe
To use your hosted unsubscribe URL for easy unsubscribe, your server must be able to:
- Identify the user by
email
oruserId
in the URL. (See Using parameters to pass data in your hosted unsubscribe URL from Step 3 above). - Accept a
GET
request to direct the user to your preference center. - Accept a
POST
request to process the easy unsubscribe request. Your server's response to thePOST
request must function as a one-click unsubscribe, and cannot redirect to a page.
Additionally, the URL must be the same for both requests.
# Accepting a GET
request
When a user clicks on the link within the email body (set using the
{{hostedUnsubscribeUrl}}
merge parameter), this sends a GET
request to your
URL, which should direct the user to the page for your custom preference center.
# Accepting a POST
request
When a user uses easy unsubscribe from their inbox, the inbox provider sends an
empty POST
request to your server.
When receiving the POST
request, your web server should:
- Send an API request to Iterable that unsubscribes the user from the appropriate list(s).
- If the request to Iterable is successful, send a
200
response to the inbox provider to confirm that the user has been successfully unsubscribed. - If the
POST
request fails for any reason, send a400
response to the inbox provider. This response triggers the inbox provider to defer to the mailto method instead, so you stay in compliance with easy unsubscribe requirements. (This is standard behavior for the List-Unsubscribe header and not specific to Iterable.)
For a hosted unsubscribe URL that looks like https://example.com/unsubscribe/example?
,
the incoming easy unsubscribe POST
request looks something like this:
POST /unsubscribe/example?user@example.com HTTP/1.1 Host: example.com Content-Type: application/x-www-form-urlencoded Content-Length: 26 List-Unsubscribe=One-Click
# 4.2 Change the List-Unsubscribe header project setting
Once your hosted unsubscribe URL is set up to handle the POST request for easy unsubscribe, you can enable this feature in Iterable.
To change the project setting to use the hosted unsubscribe URL for List-Unsubscribe headers:
- In Iterable, go to Settings > Project Settings.
- Find the setting Hosted Unsubscribe URL setting and check that the URL is correct, or make changes as needed.
- Next, find the setting Use the Hosted Unsubscribe URL as the 'List-Unsubscribe' Mail Header Value.
- Toggle this setting to Yes.
- Scroll to the very bottom of the page and click Save Project Settings.
# 4.3 Contact Iterable to finish setup
Once you've made these changes, contact your customer success manager or Iterable support and ask to enable the hosted unsubscribe URL for your List-Unsubscribe headers.
You must contact Iterable to enable this feature.
This step is required in addition to changing the project setting in Iterable.
# 4.4 Test the hosted unsubscribe URL for easy unsubscribe
After you've made these changes, test your easy unsubscribe setup.
If the user is successfully unsubscribed, the hosted unsubscribe URL is set up correctly and is working as expected.
If the user is not unsubscribed, or if the easy unsubscribe link doesn't work as
expected, review the setup of your hosted unsubscribe URL in project settings,
and the POST
request handling.
# Step 5: Use the hosted unsubscribe URL in templates
When you make a marketing email template, Iterable checks the content for
presence of an unsubscribe link (see Unsubscribe Links
To use your custom subscription preference center's URL as the opt-out link,
use the {{hostedUnsubscribeUrl}}
merge parameter in your email templates.
When you use the {{hostedUnsubscribeUrl}}
merge parameter, Iterable adds the
URL as entered in project settings. Your URL may already include parameters
like email
or userId
to identify the user.
However, you can add additional parameters in the message template by appending
them to the merge parameter. When you do this, we recommend using &
as the
first character instead of ?
.
# Attributing unsubscribes to a specific campaign and template
If a user navigates to your email preference center through a
{{hostedUnsubscribeUrl}}
link, you may want to attribute unsubscribe events
back to the campaign or template in which they clicked the link. To determine
the relevant campaign and template ID, you can pass attributes in one of two
ways:
- URL parameters
- Cookies
NOTE
This tracking advice applies to clicks on the link created by the
{{hostedUnsubscribeUrl}}
merge parameter (for example, in Iterable
templates). It does not apply to clicks on the easy unsubscribe link from the
List-Unsubscribe
header. To learn more about how Iterable tracks events
sourced from the List-Unsubscribe headers, read Tracking easy unsubscribe clicks
# URL parameters
You can append userId
, campaignId
, and/or templateId
query parameters
to your hosted preference center URL (on the Settings > Project Settings
screen), and use these parameters to attribute the unsubscribe event to a user,
campaign, and template. To learn how to do this, read Using parameters to pass data in your hosted unsubscribe URL.
For example, your preference center's URL might be something like:
https://www.example.com/accounts/preferences?email={{#urlEncode}}{{email}}{{/urlEncode}}&campaignId={{campaignId}}&templateId={{templateId}}
Your server can then access email
, campaignId
, and templateId
as needed.
# Cookies
When a user clicks a link in an email sent by an Iterable campaign, Iterable sets browser cookies for your project's link tracking domain.
If your hosted subscription preference center shares a root domain with your Iterable project's link tracking domain, it can use the values stored in these cookies to find the campaign and template to associate with the unsubscribe.
For example, if a project's link tracking domain were links.example.com
and its subscription preference center URL were unsubscribe.example.com
,
the web server for the subscription preference center could access these
cookies to get the relevant campaignId
and templateId
.
Iterable sets the following cookies:
-
iterableEndUserId
- The recipient's e-mail address. This cookie expires in one year. This cookie is set for email-based projects only.NOTE
To identify user for hybrid or userID-based projects, pass the user identifier as a URL parameter using Handlebars. To learn how to do this, read Using parameters to pass data in your hosted unsubscribe URL.
iterableEmailCampaignId
- The unique ID associated with the email's Iterable campaign. This cookie expires in 24 hours.iterableTemplateId
- The unique ID associated with the email's Iterable template. This cookie expires in 24 hours.iterableMessageId
- A unique ID associated with a specific send of a specific campaign to a specific user. If the same user ever receives the same campaign more than once, each message will have a uniqueiterableMessageId
. This cookie expires in 24 hours.
Once you have the campaignId
and/or templateId
, your web server should
include them in its call to POST /api/users/updateSubscriptions
.
For example, the request body might look similar to this:
{ "email": "user@example.com", "unsubscribedChannelIds": [100], "unsubscribedMessageTypeIds": [1, 2, 3, 4, 5], "campaignId": 123, "templateId": 456 }
DANGER
Use your server (not client-side JavaScript) to make API calls that fetch and modify a user's subscription preferences. For more information, read Make API calls from your server, not the browser.