Iterable FAQs | Comparably
Iterable Claimed Company
Iterable is the AI customer engagement platform built for enterprise scale, loved by teams, and trusted by global brands like Priceline, Fabletics, Blockchain, and Box. It transforms data into action, powering intelligent, personalized experiences across every channel to drive measurable growth. Iterable gives teams the speed to move, the governance to stay in control, and the flexibility to continuously optimize performance at scale. With Iterable, customer engagement isn’t just a tactic—it’s a growth engine. Learn more at www.iterable.com. read more
EMPLOYEE
PARTICIPANTS
42
TOTAL
RATINGS
455

Iterable FAQs

Iterable's Frequently Asked Questions page is a central hub where its customers can always go to with their most common questions. These are the 287 most popular questions Iterable receives.

Frequently Asked Questions About Iterable

  • Use snippets to reuse the same content across multiple templates. For

    example, a snippet might contain a repeatedly used header, call-to-action

    block, or footer. Editing a snippet causes all templates that reference it to receive the

    updated content. This is a more efficient workflow than manually editing the

    same content multiple times in multiple templates.

    # Table of contents

    Creating or editing a snippet Example snippet

    Using a snippet in a template

    # Creating or editing a snippet To create or edit a snippet, follow these steps:

    Navigate to Content > Snippets to bring up the Manage Snippets

    screen. #

    To create a new snippet, click Create New Snippet; to edit an existing

    snippet, click its name.

    The Create a Snippet screen appears.

    Provide a Snippet Name. This name will be used to include the snippet in a template. It can

    contain letters, numbers, spaces, dashes, and underscores.

    WARNING Changing the name of an existing snippet breaks any template that

    references it by its old name. If you change a snippet's name, be sure to

    update all templates that rely on it.

    To pass data to a snippet, use Positional Parameters. A snippet's content might need to change based on the value of a user

    profile or event field. For example, a snippet might select a product image based on a user

    profile's favoriteColor field. It's possible, though, that one template might want to consider the

    recipient's favoriteColor, while another needs to look at the

    lastPurchasedColor. If the snippet is hard-coded to look at a

    particular field, it can't be re-used in both of these scenarios. To solve this problem, don't reference specific user profile or event

    fields in snippets. Instead, pass data to snippets as positional

    parameters: variables sent from the template to the snippet. Snippets

    that make use of positional parameters aren't tied to specific user

    profile or event fields and can be reused more broadly. To add positional parameters to a snippet:

    Click Add New Positional Parameter.

    In the Key input, specify the parameter's name. For example, specifying a Key of firstName allows the snippet

    to access any value passed to that parameter as {{firstName}}.

    Add as many positional parameters as needed.

    Enter a Description that clarifies what the snippet is and where it

    should be used.

    In the Markup input, specify the content of the snippet. As you create or update a snippet's content, keep in mind the following:

    The specific editor available for modifying snippet content depends on

    the Use WYSIWYG Template Editor setting in

    Settings > Project Settings. For snippets that will be used in SMS messages, push notifications,

    or web push notifications, only use plain text (no HTML). Changing an existing snippet impacts all templates that reference it

    (including those tied to live campaigns).

    To reference a user profile field, event field, or positional parameter,

    use a Handlebars expression

    such as {{userProfileField}} or {{#if parameterName}}.

    To reference a field from a data feed:

    Use double curly braces to reference data feed data. For example:

    {{fieldInDataFeed}}. In the template that references the snippet, open the

    Advanced Options tab. On this tab, check Enable Template Generation Using Data Feeds

    and Merge the Data feed and User Contexts.

    Typical CSS precedence rules apply to any CSS contained in a snippet:

    Inline CSS (with the HTML style attribute) overrides CSS rules

    in a style tag. A more-specific selector takes precedence over a less-specific one. If two CSS rules have the same specifity, the one that appears

    later in the code takes precedence. A CSSrule with!importantalways takes precedence.

    Close all HTML tags (unless you're intentionally leaving a tag open so

    that the template can close it). Templates can make use of CSS styles defined in a snippet.

    After editing the snippet, click Save. This creates (or updates) the

    snippet and allows templates to reference it.

    # Example snippet The following properties describe a snippet that displays either a greyscale

    or color version of some social media icons, depending on the value of a

    passed-in positional parameter:

    Snippet Name socialMediaIcons

    Positional Parameters useColor

    Description Displays a greyscale or color collection of social media icons, depending

    on the boolean value passed to the useColor parameter.

    Markup {{#if useColor}}

    <br />

    <img alt="Icons" src=".../socialMediaColor.png" />

    <br />

    {{else}}

    <br />

    <img alt="Icons" src=".../socialMediaGreyscale.png" />

    <br />

    {{/if}

    (source view)

    Using a snippet in a template To insert a snippet in a template, follow these steps:

    Navigate to Content > Templates and create a new template or open an

    existing one.

    On the Edit Template screen, click Insert Snippet.

    In the Insert a Snippet window, select the snippet you'd like to

    insert.

    If the snippet contains HTML, toggle on the Render HTML switch. Enabling this option changes the Handlebars for inserting the snippet

    so that it uses triple curly braces rather than double curly braces.

    Triple curly braces cue Iterable to render the HTML in the template as

    HTML rather than as plain text.

    If the snippet requires any positional parameter values, specify them

    in the Handlebars input, after the name of the snippet.

    NOTE When passing values to a snippet's positional parameters, templates can

    specify user profile fields, event fields, or literal valuesall of which

    can have different types (numbers, strings, boolean values, etc.). Make

    sure to pass parameter values that make sense; for example, don't provide

    a string (such as a name) for a positional parameter that the snippet

    uses in a numeric comparison.

    Click the Copy button.

    In the appropriate place in your template, paste the text copied from the

    Insert a Snippet window.

    To preview the template, including its snippet content, choose

    Preview > Preview With Data or Preview > Preview on Devices. On the Preview on Devices screen, click Regenerate Previews to

    make sure you see up-to-date content.

    View Article
  • Universal merge parameters are parameters that are available for all

    clients regardless of setup. Below is a list of all universal parameters that

    can be used in your templates.

    # List of available merge parameters

    View in browser URL: {{viewInBrowserUrl}}

    Unsubscribe URL : {{unsubscribeUrl}}

    Hosted unsubscribe URL: {{hostedUnsubscribeUrl}}

    Unsubscribe message type URL: {{unsubscribeMessageTypeUrl}}

    Campaign name: {{campaignName}}

    Campaign ID: {{campaignId}}

    Recurring campaign ID: {{recurringCampaignId}}

    Template ID: {{templateId}}

    Client Template ID: {{clientTemplateId}}

    Channel ID: {{channelId}}

    Message type ID: {{messageTypeId}}

    Recipient email: {{email}}

    Company name: {{companyName}}

    Company address: {{physicalAddress}}

    Current date: {{now}} For example, "Oct 5, 2018"

    Current date: {{now format='MMMM dd, yyyy'}} For example, "October 5, 2018"

    Current date: {{now format='MM/dd/yy'}} For example, "10/05/2018"

    Current year: {{now format='yyyy'}} For example, "2018"

    Date, full format: {{now format='full'}} For example, "Monday, December 12, 2016"

    Date, custom format:{{now format='E, MMMM dd, yyyy'}} Sample output for this custom format: "Mon, December 10, 2018"

    Date five days from today: {{dateMath "now" "+5d"}}

    # Example usage

    # viewInBrowserUrl

    {{viewInBrowserUrl}} provides a link to a web version of your email. The following example shows {{viewInBrowserUrl}} being used in the

    WYSIWYG editor: # The following example shows {{viewInBrowserUrl}} being used in source code: <a href="{{viewInBrowserUrl}}" target="_blank">View this email in your browser</a>

    NOTE Clicking this link in an email proof will show an error message.

    # unsubscribeUrl

    {{unsubscribeUrl}} inserts a link to unsubscribe from the channel associated

    with the message. By default, Iterable auto-appends the unsubscribe

    block. If this feature is disabled, you must include {{unsubscribeUrl}},

    {{unsubscribeMessageTypeUrl}} or {{hostedUnsubscribeUrl}} in emails sent

    through a marketing channel. To learn more, read

    Message Channels and Message Types Overview. The following example shows {{unsubscribeUrl}} being used in the WYSIWYG

    editor: The following example shows {{unsubscribeUrl}} being used in source code: <a href="{{unsubscribeUrl}}">unsubscribe</a>

    # hostedUnsubscribeUrl

    {{hostedUnsubscribeUrl}} inserts the link to your hosted unsubscribe page

    or email preferences center. Set this up in your Iterable

    project settings. The following example shows {{hostedUnsubscribeUrl}} being used in the

    WYSIWYG editor: The following example shows {{hostedUnsubscribeUrl}} being used in source

    code: <a href="{{hostedUnsubscribeUrl}}">Update subscription preferences</a>

    NOTE If you wish to add parameters to the end of the hosted unsubscribe URL, it is

    best to type them in on the project settings

    page instead of in the template body. However, if you do add the parameters

    to the template body, use & as the first character of your parameter

    string instead of ?.

    # unsubscribeMessageTypeUrl {{unsubscribeMessageTypeUrl}} inserts the link to unsubscribe from the

    message type associated with the message. By default, Iterable will

    auto-appends the unsubscribe block. If this feature is disabled,

    you must include {{unsubscribeUrl}}, {{unsubscribeMessageTypeUrl}}

    or {{hostedUnsubscribeUrl}} in emails sent through a marketing channel.

    To learn more, read Message Channels and Message Types Overview.

    The following example shows {{unsubscribeMessageTypeUrl}} being used

    in the WYSIWYG editor: The following screenshot shows {{unsubscribeMessageTypeUrl}} being used

    in source code: <a href="{{unsubscribedMessageTypeUrl}}">Unsubscribe from Iterable's Newsletter Messages</a>

    # campaignId

    {{campaignId}} inserts the numerical ID of the campaign into the template. The following example shows {{campaignId}} being used in a template: This example would render text similar to the following:

    # recurringCampaignId {{recurringCampaignId}} inserts the campaign ID of the recurring (parent)

    campaign. This could be useful in a case where you want to include the parent

    campaign ID in a custom link parameter for attribution purposes (for example,

    if you want to attribute user engagement related to entire series of

    newsletters instead of to a single month's).

    # email

    {{email}} inserts the recipient's email address into the template. The following example shows {{email}} in the template editor: In an email, this would appear as follows:

    # companyName {{companyName}} inserts your company's name, which you set as the project

    name in your project settings.

    # physicalAddress

    {{physicalAddress}} inserts your company's physical mailing address, which you set in your project

    settings.

    You must include the address in your emails to comply with CAN SPAM laws. By

    default, Iterable auto-appends your unsubscribe block, which will include the

    address you have entered in project settings. If you have turned off this

    feature, then you can use {{physicalAddress}} in your emails when coding your

    unsubscribe block. The following example shows {{physicalAddress}} in the template editor: In an email, this would appear as follows:

    now

    {{now}} will give you current time at time of send. You can then format this

    date according to your needs: {{now format='YYYY-MM-dd'}}`

    NOTE If you are using the WYSIWYG editor, be sure to use single quotes. If you use

    double quotes around the format, it won't save properly.

    The following example shows {{now}} in the template editor: In an email, this would appear as follows:

    View Article
  • Iterable projects provide two levels of metrics:

    Campaign-level (specific to a campaign; covered in this article) Aggregate-level (across multiple campaigns; covered in

    Viewing Aggregate Campaign Metrics )

    NOTE Read Metrics Definitions,

    SMS Campaign Metrics,

    and Push Campaign Metrics

    to learn more about different metrics in Iterable.

    # Table of contents

    Campaign-level metrics

    Email template

    Heatmaps

    Exporting data

    Displaying metrics

    # Campaign-level metrics

    NOTE This guide describes how to view standalone campaign metrics. To learn how to

    view metrics for campaigns associated with workflows, read

    Workflow Analytics.

    To view the metrics for a specific campaign, open the campaign in Iterable.

    Metrics are visible for campaigns that are running or finished. At the top of the campaign's page, you will see the overall campaign details

    like launch time, the list used, the status of the campaign, which template

    was used and the experiment details. The list size at send time is equal to the total number of

    subscribers on the list minus the number of subscribers who have unsubscribed

    from the message channel delivering the message. Therefore, the list

    size may differ from the actual send size. #

    TIP To learn more about message channels and types, read

    Message Channels and Message Types Overview.

    # Email template Click the View Email button to navigate to the template used in the

    campaign:

    # Heatmaps Click the View Heatmap button to navigate to a heatmap that describes

    where users are clicking in a message: View different heatmaps for each of the variations of a campaign experiment

    by clicking on the dropdown on the left-hand side above the heatmap table: Use the search bar to filter for specific links or text. You can also view

    the raw link data by toggling on the "Show raw link data," which is useful

    for showing link stats for highly dynamic content.

    # Exporting data Click the Export Data button to export a variety of different reports as

    a CSV file. You can drill down to the specific individuals who opened,

    clicked, or purchased from your campaigns. Export data such as email clicks, purchase, email unsubscribes, hosted

    unsubscibe clicks, email or spam complaints, custom events, bounces,

    opens, subscibes, sends, and uninstalls.

    # Displaying metrics At the bottom of the page, select metrics,

    date ranges, and experiment variations.

    TIP Remember to select which metrics you want to view from the dropdown on the

    right - none of them will be selected by default.

    # Events over time The following graph displays open, click, unsubscribe, bounce, and other

    events over time:

    # Segment analysis The segment analysis grid shows various metrics by user segment:

    # Opens breakdown The opens breakdown pie chart shows statics for Unique opens and

    Not yet opened:

    # Device type breakdown The device type breakdown shows the devices that have been used to open a

    campaign. Some of the slices on this pie chart might include:

    iPhone: Apple's Mail app on an iPhone

    iPad: Apple Mail app on an iPad

    Gmail: Gmail app or website

    Android: Non-Gmail app opens on Android

    : Unknown user agent and device

    NOTES

    A Gmail slice on the pie chart includes users who used a Gmail app or

    the Gmail website, since Iterable is not able to distinguish between the two. If a user used a non-Gmail email client to open an email sent to a Gmail

    account, the open is counted in a non-Gmail bucket. For example, if a user

    opened such an email using the Mail app on the iPhone, the open would be

    counted by Iterable as an iPhone open.

    Map The world map shows locations where users have engaged with your campaigns:

    View Article
  • Iterable can create and send push notification campaigns to iOS and Android

    devices, all from a single message template. Push notifications can be customized with sounds, images, videos, and action

    buttons (iOS and Android support different options)all the elements needed

    to create engaging and valuable content for your users. Iterable's push

    notification editor provides live previews as you edit, validates errors, and

    can be used to integrate data stored on a user's Iterable profile into a

    message. This guide describes how to use Iterable to set up your mobile apps to send

    push notifications, create a push notification template, send a push

    notification campaign, and use workflows to send push notifications.

    # Table of contents

    Setting up your mobile apps

    Creating a push notification template

    Using the push notification template editor

    Basic push notification information

    Expert mode

    Deprecated push notification fields

    Saving the push notification template

    Creating a push notification campaign

    Using a workflow to send a push notification

    Further reading

    # Setting up your mobile apps Before sending push notifications, work with your mobile engineers to

    configure your iOS and Android apps. For more information, take a look at the

    following resources:

    iOS:

    Setting Up iOS Push Notifications Iterable's iOS SDK

    iOS SDK Release Notes

    Android:

    Setting up Android Push Notifications Iterable's Android SDK

    Android SDK Release Notes

    # Creating a push notification template To send push notifications with Iterable, first create a push notification

    template and provide basic details about its name, message type, title, text,

    push open action, and any associated rich media. Then use expert mode to

    further customize the template's configuration as necessary. To create a push notification template, navigate to Content > Templates

    click Create New Template, and select Push. This brings up the push

    notification template editor. Snippets Overview

    # Using the push notification template editor As you edit the fields in the push template:

    The preview updates as you type. Use the Apple and Android icons to switch the preview between platforms. Use Handlebars expressions to reference data contained in a user profile or

    triggering event. For example, entering {{messageTitle}} in the Title

    field references a messageTitle field on the triggering event or user

    profile (if both the user profile and the triggering event have a field with

    this name, the field on the triggering event takes precedence). Use the Insert Snippet buttons to find a snippet

    to enter into a field Use the Send Proof and Preview with Data buttons to send a test

    notification or preview your notification with data from a user's Iterable

    profile. Be sure to save the template before using these options.

    # Basic push notification information When building a push notification template, provide the following basic

    information:

    Template Name: The template's internal-facing name. Use this to find

    the right template when building a campaign. Message Type: The message type associated with the campaign.

    Message types categorize messages, allowing users to receive only the content

    they're most interested in. For more information, read

    Messages Channels and Types Overview. Title: The title text that should appear at the top of the push

    notification. Push Message: The text that should appear in the body of the

    push notification.

    Push Open Action: The action that should occur when the user taps on

    the push notification.

    Open App: Opens the app associated with the push notification. Open URL: Passes a URL to the mobile appliction's URL handler. This

    URL can deep link to specific content in the app or point to external

    content to open in a web browser. When this option is selected, the

    template editor will prompt you to provide a URL.

    Rich Push: An image or video (Android push notifications do not support

    video) and action button to associate with the push notification. Action

    buttons sit below push notifications and allow users to take immediate action

    on their content. Use them to encourage users to make a purchase, write a

    review, visit a website, share content on social media, unsubscribe from a

    list, or take some other relevant action. Options specified in this section apply to both iOS and Android push

    notifications. To configure platform-specific settings or use more than

    one action button, use expert mode.

    NOTES

    In the push notification preview, click an image to expand it. The action button shows when the push notification is expanded; if you

    don't see it, click on the preview. This section allows you to configure a single action button; to use

    multiple action buttons, see expert mode. To include images, videos, or action buttons with iOS push

    notifications, have your mobile engineers add a Notification Service

    Extension to your iOS application. For more information, read about

    Iterable's iOS SDK.

    # Expert mode To further configure the push notification, enable Expert Mode (using the

    toggle at the top of the template editor). Then, adjust the following

    settings as necessary:

    Custom Action: The name of a custom action to pass to your mobile

    application's custom action handler. Work with your team's mobile engineers

    to decide on a list of custom actions to support. This option is only

    available when Expert Mode is toggled on.

    Action Buttons: Buttons that display below push notifications, allowing

    users to take immediate action on their content. Use them to encourage users

    to make a purchase, write a review, visit a website, share content on social

    media, unsubscribe from a list, or take some other relevant action. A push

    notification can have up to three action buttons. Example action buttons on iOS and Android:

    NOTES

    Action buttons show when the push notification is expanded; if you

    don't see them, click on the preview. To include images, videos, or action buttons with iOS push

    notifications, have your mobile engineers add a Notification Service

    Extension to your iOS application. For more information, read about

    Iterable's iOS SDK.

    Options for action buttons:

    Button Text: The text that should on the button. For example, Buy now!. Identifier: A value to include on the Track Push Open event sent

    from the mobile app to Iterable after the user taps the button. Useful

    for segmenting on users that have tapped a particular push notification

    button.

    Button Type: The button's type impacts its appearance and the

    actions available to it (see below). Iterable supports three different

    types of action buttons:

    Normal Button: A button with black text. Destructive Button: A button with red text. Text Input Button: A button that displays a text input after

    being tapped. When selected, this type of button provides a

    Placeholder input for specifying placeholder text for the push

    notification's text input, and a Submit Button Text input for

    specifying the text to use on the input's submit button.

    Button Action: The action to trigger when tapping on the button. There

    are four types of button actions:

    Open App: Opens the app associated with the push notification. Open URL: Opens an external URL or a deep link to content within

    the app.

    Custom Action: Passes the provided value to the application's

    custom action handler, which is defined in the app's code. Decide in

    advance with your team's mobile engineers on a list of supported custom

    actions. The Open App option nested under Custom Action causes

    the app to come to the foreground to execute the action.

    Unchecking this option executes the action with the app in the

    background.

    Track Only: Sends Iterable a Track Push Open event with the

    associated button identifierwithout opening the app or redirecting the

    user. This option is useful for buttons that dismiss the push

    notification. This button action is available for destructive buttons

    and text input buttons.

    # iOS-only settings

    Rich Media URL: The URL of an image, video, audio file, or animated

    GIF. Iterable validates the URL to make sure it can be rendered.

    NOTES

    In the push notification preview, click an image to expand it. To include images, videos, or action buttons with iOS push

    notifications, have your mobile engineers add a Notification Service

    Extension to your iOS application. For more information, read about

    Iterable's iOS SDK.

    Badge Count The badge count the app should show after receiving this

    push notification. This field can contain a Handlebars expression that

    references a badge count stored on the user's Iterable profile. For example,

    {{badgeCount}}.

    Wake App: Causes the app to wake up in the background to perform a

    background update. Un-checking this setting ensures that the user doesn't

    wake the application and cause it to ping your system's servers.

    # Android-only settings

    Rich Media URL: The URL of a hosted image. Iterable validates the URL

    to make sure it can be rendered. Google recommends using an aspect ratio of

    2:1 for rich media push messages.

    NOTES In the push notification preview, click an image to expand it.

    # Advanced Options

    Custom Sound: The name of the sound file to play when the push

    notification arrives. For the sound file to play, your mobile engineers must

    bundle it in your mobile application. For more information, read

    Setting Up iOS Push Notifications

    and Setting up Android Push Notifications. Enable Template Generation Using Data Feeds: Data feeds query external

    web services at send time, providing the results to Iterable so it can

    customize the messages sent by a campaign. This option enables data feeds in

    the push notification template. For more information about using data feeds

    in Iterable, read Rendering Templates with Data Feeds.

    # Custom Metadata Additional JSON data to send with the push notification. This data will be

    available for your apps to process as necessary. This data can be used to control the state of your application. For example,

    if a user reaches VIP status and a push message is congratulating them for

    this achievement, the notification might contain custom data telling the app

    that the user is now a VIP. The app could process this custom metadata and

    accordingly change the home screen or app colors.

    # Deprecated push notification fields The following fields have been deprecated and are no longer available for new

    templates. Instead, use the Rich Push, Push Open Action, and

    Action Buttons options discussed above.

    iOS Deep Link Android Deep Link iOS Category

    Templates that already use these fields will continue to display

    them and work as expected

    # Saving the push notification template After configuring the push notification template, save and view a preview:

    Save the template by clicking Save Template.

    Preview the template by clicking Send Proof or Preview With Data. On the Preview with Data screen, enter an email address and click

    Load User Data to view how that user's profile data impacts the

    rendering of the push notification.

    Back in the template editor, make changes as necessary.

    # Creating a push notification campaign After configuring your mobile apps to work with push notifications and

    creating a push notification template, you can send a push notification

    campaign. Follow these steps:

    Navigate to Messaging > Campaigns and click Create New Campaign.

    Fill in the necessary details for the campaign (name, custom converstion

    metric, labels), and choose a campaign type: Blast or Triggered. For Message Medium, select Push.

    Enable Selective Push, if necessary. If you have multiple mobile apps only a subset should receive the push

    notification campaign, enable Selective Push and select the mobile

    apps to include. If you do not enable selective push, Iterable sends the push notification

    campaign to all push integrations defined in the project, regardless

    of whether or not they are assigned to mobile apps.

    NOTE Define mobile apps in Settings > Mobile Apps. For more details,

    see Setting Up iOS Push Notifications

    and Setting Up Android Push Notifications.

    Select send and suppression lists. In order for users to receive ush notification campaigns from Iterable,

    their user profiles must have a device token associated with your mobile

    app. Iterable's mobile SDKs ( iOS,

    Android ) populate

    these tokens when the app is run.

    Click Continue to Templates. Select and edit a template, or create a new one. Read

    Creating a push notification template

    for more information. After editing, saving, and previewing the template, click

    Save & Continue To Review. To activate a triggered campaign, click Activate Campaign. To send a

    blast campaign, click Send Campaign Right Now or

    Schedule Campaign for Later. After launching the campaign, you'll see its

    Campaign Analytics screen, where you can view statistics about the

    campaign. For more information about these analytics, read

    Push Campaign Metrics.

    # Using a workflow to send a push notification To use an Iterable workflow

    to send push notifications, follow these steps:

    Navigate to Messaging > Workflows.

    Select an existing workflow or click Create New Workflow to create

    a new one. Set up up the workflow as necessary.

    At the point in the workflow where you'd like to send a push notification,

    drag a Send Push node onto the workflow canvas and connect it to another

    node.

    Configure the new Send Mobile Push node by double-clicking on it.

    Provide a Campaign Name, select a custom conversion metric if

    necessary, and add Labels.

    Select a template and click Update Node. Alternatively, edit an existing template before selecting it:

    Right-click the name of a template and open it in a new browser tab.

    Edit the push notification template

    as necessary. Click Save Template. Back in the original browser tab, close the workflow node. Double-click the Send Mobile Push node to re-open it. Select the edited template and click Update Node.

    Back on the workflow canvas, click Save. Enable the workflow with the toggle in the upper-left corner of the

    workflow canvas.

    TIP To learn more about testing workflows, read Testing a Workflow.

    # Further reading

    Iterable's iOS SDK iOS SDK Release Notes Setting Up iOS Push Notifications

    Advanced iOS Push Notifications. Iterable's Android SDK Android SDK Release Notes Setting up Android Push Notifications

    Rendering Templates with Data Feeds.

    Testing a Workflow.

    Messages Channels and Types Overview.

    View Article
  • SSO allows automatic, fine-grained management of your organization's Iterable

    accounts:

    Users login through your Identity Provider (IdP) rather than create their own

    username and password You can disable logins from your IdP after a user leaves your organization

    SSO is configured through the open standard

    Security Assertion Markup Language (SAML). Iterable supports any SAML-compatible IdP. For example:

    Okta ADFS OneLogin

    # Table of contents

    Pre-existing users

    Configuring your identity provider (IdP)

    SAML settings

    Attribute statements

    Roles

    Okta example

    Configure Roles Via Okta Groups

    Configuring Iterable Okta IdP metadata

    # Pre-existing users After a user logs in to Iterable using your organization's IdP, their

    previous Iterable credentials will no longer work. Depending on your

    configuration, their assigned projects and roles may also be modified.

    # Configuring your identity provider (IdP) The following sections describe how to configure your IdP to work with

    Iterable.

    # SAML settings In your IdP, use the following SAML settings for the Iterable integration:

    Single sign-on URL: https://app.iterable.com/authenticate/saml?orgId=ORG_ID Replace ORG_ID with the your organization's ID (found by navigating

    to Settings > Project)

    Audience URI (SP entity ID): https://app.iterable.com/authenticate/saml

    Name ID format: EmailAddress

    Application username: Email

    # Attribute statements Configure your IdP to include the following attribute statements

    when authenticating with Iterable:

    firstName: the user's first name

    lastName: the user's last name

    email: the user's email address

    roles: see the Roles section below

    # Roles The roles property designates the role assigned to an Iterable user. Its

    value has two possible formats, you may only use one:

    OrgAdmin: use for organization admins, grants the user access to all

    projects and roles

    42:Contributor, 93:Publisher: A comma-separated mapping of project IDs to

    roles, allowing you to set per-project roles. The user is granted limited

    access to only the projects and roles specified.

    The Iterable project ID can be found by switching to that project in

    Iterable and navigating to Settings > Accounts

    The possible role values are Reader, Contributor, Publisher, AccountManager, and

    Admin

    For more details on these roles, see Account Roles and Permissions.

    # Okta example In Okta, an Iterable configuration should look similar to the following: #

    # Configure Roles Via Okta Groups Rather than using a static value for the roles property, Okta allows

    administrators to define this property on a group basis. This enables them to

    define different roles for different users within their organization. From the Okta Admin Console, go to Directory > Profile Editor then click the

    Profile button next to the Iterable app From there click Add Attribute and fill it in how you like, but make sure you

    set the following:

    Variable name: roles Attribute required: checked

    Return to the Assignments tab in the Iterable application. Assign a group,

    then click the Edit button. Set the roles property as desired for this group (don't use my example

    values!) Switch back to the General tab and click Edit on SAML Settings. Click Next to

    get to the Configure SAML step. Set the value of the roles User Attribute to `appuser.roles'

    # Configuring Iterable For Iterable to recognize requests from your IdP, it must be aware of your

    IdP metadata. IdP metadata is a block of XML that contains a certificate and

    application information. It should look similar to the following: <?xml version="1.0" encoding="UTF-8"?>

    <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://www.okta.com/blahblah">

    <md:IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">

    <md:KeyDescriptor use="signing">

    <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">

    <ds:X509Data>

    <ds:X509Certificate>

    SEqwY8cFuVvOjUuZJ/bhzIAW8W/oZZJkL3qD96uJzlhf1dZN3MnttFhMahKAahlNU2Kd9/Qznz2+

    kdljGHs/x7AEfFbe4mEpKi52aZAFD8gcZv4s3wnCMgzndTqEn7dx+4kVtGEh6NAzJfMVgLk50ybb

    l6otY3x6m72Jk6zhTKYZHMM9k99sWWs+T3ewq6mbVGMNNk54JdmUtzf42MxT/b9bIvLhVYDqzswy

    CFVP7oNN8VmjaI+c6BC89WYthX8gflknlC2PFQa+G4LddERIPLxTDEfQWVONoKHJhxotRvb1HLp2

    Jzlhf1dZN3MnttFhMahKAahlNU2Kd9/Qznz2+SEqwY8cFuVvOjUuZJ/bhzIAW8W/oZZJkL3qD96u

    CMgzndTqEn7dx+4kVtGEh6NAzJfMVgLk50ybbkdljGHs/x7AEfFbe4mEpKi52aZAFD8gcZv4s3wn

    bVGMNNk54JdmUtzf42MxT/b9bIvLhVYDqzswyl6otY3x6m72Jk6zhTKYZHMM9k99sWWs+T3ewq6m

    UuZJ/bhzIAW8W/oZZJkL3qD96uJzlhf1dSEqwY8cFuVvOjZN3MnttFhMahKAahlNU2Kd9/Qznz2+

    Fbe4mEpKi52aZAFD8gcZv4s3wnCMgzndTkdljGHs/x7AEfqEn7dx+4kVtGEh6NAzJfMVgLk50ybb

    6zhTKYZHMM9k99sWWs+T3ewq6mbVGMNNkl6otY3x6m72Jk54JdmUtzf42MxT/b9bIvLhVYDqzswy

    I+c6BC89WYthX8gflknlC2PFQa+G4LddECFVP7oNN8VmjaRIPLxTDEfQWVONoKHJhxotRvb1HLp2

    tFhMahKAahlNU2Kd9/Qznz2+SEqwY8cFuJzlhf1dZN3MntVvOjUuZJ/bhzIAW8W/oZZJkL3qD96u

    +4kVtGEh6NAzJfMVgLk50ybbkdljGHs/xCMgzndTqEn7dx7AEfFbe4mEpKi52aZAFD8gcZv4s3wn

    tzf42MxT/b9bIvLhVYDqzswyl6otY3x6mbVGMNNk54JdmU72Jk6zhTKYZHMM9k99sWWs+T3ewq6m

    +G4LddERIPLxTDEfQWVONoKHJhxotRvb1HLp2CFVP7oNN8VmjaI+c6BC89WYthX8gflknlC2PFQa

    hDsLV9h/c5As5qx7/zSOLmoG3W+LoABOHiXo==

    </ds:X509Certificate>

    </ds:X509Data>

    </ds:KeyInfo>

    </md:KeyDescriptor>

    <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>

    <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://some.url/sso/samle"/>

    <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://some.url/sso/samle"/>

    </md:IDPSSODescriptor>

    </md:EntityDescriptor>

    Iterable does not currently provide a user interface for specifying IdP

    metadata. Instead, please send it to your Iterable CSM and request that they

    add it to your account.

    Okta IdP metadata In Okta, IdP metadata can be found in the admin interface on your

    application configuration page, on the Sign On tab. Click

    Identity Provider Metadata.

    View Article
  • New and improved features:

    Added support for send time experiments

    Drag-and-Drop Editor now supports video

    Miscellaneous/bug fixes:

    Field Data Type mismatch errors are now flagged as 4XX error responses to the user update, user bulk update, and event track API calls

    View Article
  • This teardown evaluates the user engagement strategies of two leaders in grocery delivery, Safeway and Instacart. Who delivers a fresher experience with their email and mobile marketing?

    To view all User Engagement Teardowns, view iterable.com/teardown.

    View Article
  • Iterable allows you to send campaigns at a specific local time depending on

    the user. For example, a campaign can be delivered at exactly 9am Pacific,

    Eastern or Samoan time.

    # Instructions You can enable this feature if you provide either a timeZone or ip field

    for users. These fields are case and space-sensitive. For timeZone, the time zone will need to be formatted as described

    by Wikipedia's List of tz database time zones.

    Here's an example of how it would look in CSV: # For ip, you will need to include the user's ip address. Here's the CSV

    example:

    WARNING If you provide the ip field in an import and have the

    Enable User IP to Location Lookup

    setting enabled, Iterable will automatically do a geoLookup and fill in the

    city, country, region, state, and timeZone fields on the user

    profile if this information is returned by the geo lookup. You can send blast campaigns and workflow campaigns at a specific local time.

    In blast campaigns, you can choose this option in the final launch step of

    the campaign creation process.

    # Starting and fallback time zones for blast campaigns When scheduling a blast campaign, you have the option to choose both a

    starting and fallback time zone (see below). The starting time zone is used to determine when the campaign will start

    sending. No messages will be sent before the selected time in this time zone.

    Anyone with a timeZone value that is east of the starting time zone (up

    until the international date line) will receive the email at this starting

    time. The fallback time zone will dictate when users who do not have the

    timeZone field set will be sent the campaign. Say you set your email to send today at 3:00pm, with a starting time zone of

    America/Chicago and a fallback time zone of `America/Honolulu``:

    User Location

    timeZone field Send time Note

    Bob San Francisco, CA America/Los_Angeles 3pm PST/5pm CST

    Sally New York, NY America/New_York 4pm EST/3pm CST Sally is east of the starting time zone, so she is sent the email immediately at 3pm CT.

    Wendy San Francisco,CA 6pm PST/3pm HST Wendy doesn't have a timeZone on her user profile, so she is sentthe emailwith the fallback time zone.

    Delaying a workflow until a specific time In workflows, you can send at a specific local time by adding a delay prior

    to a message send node that will delay until a specific time:

    View Article
  • Iterable uses data feeds to populate campaign messages with data pulled from

    web services. Since Iterable can pass parameters to these services, each data

    feed query can fetch data relevant to a specific user. This makes it possible

    to use dynamically-queried data to send personalized, relevant messages. In Iterable, a single template can reference one or many data feeds, which

    means that data from multiple sources can be used to customize a single

    message. Iterable data feeds support web services that return JSON, XML, RSS,

    or Atom data. This document describes how to use data feeds in an Iterable campaign.

    # Set up a web service A data feed defined in Iterable retrieves its data by querying a web service. For example, the JSON data below might come from a web service that returns

    product recommendations based on a user's prior purchases. The data includes:

    Information about a user's past purchase Three recommended products, each of which includes a name, description,

    price, and image URL.

    {

    "pastPurchase": "Hot Dog Halloween Outfit for Cats",

    "suggestedProduct": [

    {

    "name": "Deluxe Cat Tree",

    "description": "A jungle for your favorite feline buddy",

    "price": 160,

    "imageUrl": "http://img-cache.cdn.gaiaonline.com/0b4be3af7262e023cce39cffa697d4cd/http://i324.photobucket.com/albums/k331/michellepaints/CC_Cat_Tree.jpg"

    },

    {

    "name": "Catnip Mouse Toy",

    "description": "Cats go absolutely crazy for this realistic mouse toy!",

    "price": 4,

    "imageUrl": "http://www.crystalclearpet.com/shop/treats/images/catnip-large-mouse-11077a.jpg"

    },

    {

    "name": "Set of 3 Furry Sticks",

    "description": "Dangle this enticing toy in front of your kitty!",

    "price": 5,

    "imageUrl": "http://i01.i.aliimg.com/wsphoto/v1/1944996867/Freeshipping-font-b-Rabbit-b-font-font-b-Fur-b-font-Strip-Funny-Cat-Stick-Cat.jpg"

    }

    ]

    }

    A sample web service for this data exists here: http://static.iterable.com/sample-data-feeds/sample_data_feed.json.

    Click the URL to see the JSON it returns.

    NOTE The web service queried by a data feed should use a response charset of

    UTF-8.

    # Customize the response for each user To personalize the data returned by a data feed for each of a campaign's

    recipients, pass user-specific merge parameters to the data feed's URL. A

    data feed URL that uses merge parameters might look something like the

    following: http://host/sample_data_feed.json?{{#urlEncode}}email={{email}}{{/urlEncode}}

    Here, the recipient's email is passed in double curly braces (Handlebars),

    and it is URL-encoded by the #urlEncode helper. The web service hosted at

    this URL must expect the passed-in URL parameters and use them to look up

    personalized data. Before making a data feed query, Iterable replaces any parameters found in

    its URL with values from a user's profile or with data included on the event

    that triggered the campaign (using the POST /events/track

    API endpoint). This makes it possible to use fields other than email

    (such as userId).

    NOTE Certain merge parameters related to the campaign itself, like

    {{campaignId}} and {{campaignName}}, are generated at campaign send time.

    These fields may appear blank when previewing the template with data.

    # Data feed HTTP response codes When querying a data feed URL, Iterable interprets the resulting HTTP

    response code as follows:

    HTTP response code Meaning Iterable behavior

    200 OK (Success) Data feed content will be used to customize a message template as necessary before sending

    429 Too many requests Retry data feed call every three minutes, up to 20 times

    4XX Invalid parameters or invalid feed URL Will not send

    5XX Server error Retry data feed call every three minutes, up to 20 times

    Other Unrecoverable error Will not send

    Wikipedia provides more detail

    about HTTP status codes.

    # Data feed response times Iterable expects a data feed to return a complete response within ten

    seconds; otherwise, it will retry the query three minutes later. After five

    unsuccessful query attempts, Iterable will skip sending the message to the

    user in question.

    # Create a data feed to query the web service To use data feeds in a campaign, first define the data feeds in Iterable:

    Navigate to Content > Data Feeds

    For each necessary data feed, click the Create New Feed button and

    provide the required information: #

    Name: The name of the data feed. Used to select it when using it in

    a campaign.

    Format: The type of data the data feed will query from a web

    service.

    Template Handlebars Alias: An alias that can be used by a template

    to reference data from this data feed.

    For example, if the data feed returns a field1.field2 property,

    setting an alias of my_alias allows a template to reference this data

    as [[my_alias.field1.field2]]. Otherwise, the data would be

    available as [[field1.field2]]. Data field aliases clarify which data feed an expression

    references, especially in situations where a single template uses

    multiple data feeds.

    Authorization Token: An authorization token to include with the

    data feed request. Click Add New Custom HTTP Header to add custom HTTP headers

    required by the URL (as necessary).

    # Reference data feeds in a template To reference a data feed in a template:

    Create a template by navigating to Content > Templates and clicking

    Create New Template. Alternatively, do this while creating a campaign. When entering text for the template's content, reference a data feed with

    either:

    Double square brackets

    Double square brackets are the default way to access data feed

    data. For example, the following expression references the price of the

    first item in the suggestedProduct array of the data feed defined

    above: [[suggestedProduct.[0].price]].

    Double curly braces

    Double curly braces are the default way to reference user profile

    data.

    However, if Advanced Options > Enable Template Generation Using Data Feeds > Merge the Data Feed and User Contexts

    is enabled for the template, double curly braces can reference both

    user profile data and data feed data.

    For example, the following code references the price of the first item

    in the suggestedProduct array of the data feed defined above:

    {{suggestedProduct.[0].price}}. If the expression contained in double curly braces can reference either

    a value from the user's profile or a data feed, Iterable will use the

    user profile data.

    Because of this, it's possible to write a single Handlebars

    expression that pulls user profile data when it's available, but

    otherwise uses data feed data.

    # Using aliases to reference data feed data Templates can use aliases to reference data feed data, so long as:

    The data feeds in question have aliases defined in Integrations > Data

    Feeds. In the template,

    Advanced Options > Enable Template Generation Using Data Feeds > Use Data Feed Alias is enabled.

    For example, a template might reference a data feed having alias my_alias

    by using syntax such as: [[my_alias.suggestedProduct.[1].price]].

    # Example template Here is an example of a template that uses data from both a data feed and a

    user profile:

    # Integrate data feeds into a campaign Iterable can query data feeds at campaign send time (once per recipient, to

    maximize personalization) or at campaign design time (only one time,

    minimizing load on the server that hosts the web service). These two options

    are described in more detail below.

    # Querying data feeds at campaign send time (once per recipient) The most common way to fetch a data feed is at campaign send time, once per

    recipient. With this approach, data from the feed is both up-to-date and

    customized for the recipient (assuming user-specific merge parameters are

    included in the data feed's URL). To have a campaign query data feeds at send time for each recipient:

    When creating a campaign, on the Select Template step, select the

    template whose contents reference the data feeds in question. Scroll to the bottom of the screen and click Continue to Design. Navigate to the Advanced options tab.

    Select data feeds:

    Check Enable Template Generation Using Data Feeds. Click the text input below the checkbox to view a list of the data

    feeds available to the project. Select all necessary data feeds (select one or many, as necessary).

    Set other data feed options on the Advanced options tab:

    Aliases

    If the template's contents use aliases (as defined for each data

    feed in Content > Data Feeds) to reference data feeds,

    select the Use Data Feed Alias checkbox. For example, a data feed might have an alias such as my_alias.

    With Use Data Feed Alias enabled, the template can access the

    data feed's data as follows: [[my_alias.field1.field2]]. Otherwise,

    this data would be available as [[field1.field2]]. Aliases can make templates more readable and provide a way to

    disambiguate between two similar data feeds.

    Merging data feed and user contexts If the selected template uses curly braces to reference data feeds,

    enable Merge the Data Feed and User Contexts.

    Caching

    To cache the template's data feeds (to reduce load on the servers

    that host them), select the Cache Data Feed Response checkbox. For each recipient, Iterable will determine the data feed URL to

    query by substituting parameters from the user's profile into the

    data feed's pre-defined URL (as necessary). If that URL has been

    cached within the past hour, the cached response will be used;

    otherwise, Iterable will query the URL.

    NOTE Iterable will re-cache the data feeds for a template every hour while

    sending the campaign.

    Save the template by scrolling to the bottom of the page and clicking

    Save Template.

    Preview how the template will render with data feed data:

    Click Preview and select Preview with Data. On the Preview with Data screen, in the Load User Data text

    input, enter an email address associated with a user profile. Click

    Load User Data.

    Under Load Data Feed data, select the data feed to use while

    previewing the template. Click Load Feed, and the data feed will

    load.

    NOTES

    It is only possible to preview one data feed at a time. If your

    template relies on multiple data feeds, preview each one

    sequentially.

    If your template uses an alias to reference a data feed, for the

    Preview With Data screen to work properly you must manually edit

    the feed's loaded data and wrap it in a top-level element with the

    same name as its alias. For example, for a data feed having alias

    my_alias, wrap the data as follows: { "my_alias": { "field1": { "field2": "testing" } } }

    Examine the preview to make sure it looks as expected. Remember, if the

    data feed changes prior to the campaign being sent, the actual campaign

    will differ from the preview.

    # Querying data feeds at campaign creation time Alternatively, Iterable can query a data feed one time during campaign setup,

    immediately integrating that data into the campaign's copy of the template.

    This minimizes load on the server that hosts the data feed, since the HTTP

    request is made only one time. However, with this approach it is not possible

    to personalize the data feed request for a specific user. To query a data feed during campaign creation:

    When creating a campaign, on the Select Template step, click on the

    template whose contents reference the data feed in question. Scroll to the bottom of the screen and click Use Template with Data Feed.

    In the Select Data Feed to Merge Into Template modal window that

    appears, select the data feed from which data should be queried. Click

    Use This Data Feed.

    NOTE When querying a data feed at campaign creation time (as opposed to send

    time), it is only possible to use reference one data feed in a template.

    To preview the template:

    Click the Preview button and choose Preview with Data. Verify that the template renders as expected.

    Finish setting up the campaign On the bottom of the Edit Template screen (part of campaign setup), click

    Save & Continue to Review to finish setting up the campaign.

    View Article
  • Using Kickdynamic with Iterable enables you to streamline email template

    creation and populate your emails with dynamic content that renders at the

    time of open.

    NOTE This integration requires an Iterable account and

    a Kickdynamic account. If youre not already an Iterable client,

    request a demo

    to discuss the how the Iterable and Kickdynamic integration can work for you.

    # Image tag integration into template HTML The Kickdynamic image tag integration into Iterable is extremely light

    weight. Once a campaign has been set up in Kickdynamic, a dynamic tag will be

    displayed similar to the tag below. The image tag can include merge

    parameters, which will be populated by Iterable at the time of send based on

    Iterable CRM data.

    This screenshot shows an example image tag produced by Kickdynamic: #

    Login to your Iterable account and navigate to the email template where

    you would like to insert the Kickdynamic content and paste it here:

    Thats it. Your emails will now render Kickdynamic content upon send.

    NOTE You can also pre-render this content using the Preview function

    located at the bottom of the page shown above.

    Other ways to integrate Kickdynamic Kickdynamic also supports the following integration methods. Please contact

    your Kickdynamic CSM to set them up if the image tag integration does not

    suit your needs.

    API (JSON) CSV XML

    View Article
  • Iterable partners with

    Stitch Data to enable

    clients to export and replicate all their Iterable data in the data warehouse

    of their choice.

    NOTE This integration requires an Iterable account and a

    Stitch Data account. If youre not already an Iterable client,

    request a demo

    to discuss how the Iterable and Stitch Data integration can work for you.

    # Table of contents

    Add Iterable as a Stitch Data Source

    Generate an Iterable webhook URL

    Set up webhooks in Iterable

    Replication

    Webhooks and historical data

    Method

    Query for the latest data

    Schema

    Webhook URLs & security

    # Add Iterable as a Stitch Data Source

    Sign in to your Stitch account. On the Stitch Dashboard page, click the Add Integration button. Click the Iterable icon.

    Enter a name for the integration. This is the name that will display on the Stitch Dashboard for the

    integration; itll also be used to create the schema in your destination.

    For example, the name Stitch Iterable would create a schema called

    stitch_iterable in the destination.

    WARNING Schema names cannot be changed after you save the integration.

    Click Save Integration.

    # Generate an Iterable webhook URL

    Once Stitch has successfully saved and created the Iterable integration,

    youll be redirected to a page that displays your Iterable webhook URL and

    token (which is blurred in the image below): set up webhooks in Iterable

    Click the Copy button to copy it. Note that this particular URLwon'tdisplay in Stitch again once you click

    Continue. Think of this URL like you would your login or API credentials:

    keep it secret, keep it safe. You can, however, generate another URL

    should you need it. Onceyou'vecopied your webhook URL, click Continue to wrap things up

    in Stitch.

    # Set up webhooks in Iterable The last step is to set up webhooks in your Iterable account.

    Sign into your Iterable account. Click Integrations > System Webhooks. In the Endpoint field, paste your Stitch-generated webhook URL. Click Create Webhook. After the webhook is saved, click the Edit button on the far right to

    select the events you want to track.

    Check the events you want to track:

    Your changes will save automatically. Youre good to go.

    # Replication Afteryou'vesuccessfully connected your Iterable integration, Stitch will

    continuously replicate your webhook data into your data warehouse.

    # Webhooks and historical data Because Iterable data is sent to Stitch in real-time, this means that only

    new records are replicated to your data warehouse. Most webhook-based

    integrationsdon'tretain historical data due to this as-it-happens approach. In the event that our webhook service experiences downtime, you may notice

    some lag between an event occurring and the data appearing in your data

    warehouse.

    # Method This version of Stitchs Iterable integration uses append-only replication.

    Append-only replication is a type of incremental replication where newly

    replicated data is appended to the end of a table. Existing rows are not

    updated; updates are added to the end of the table as new rows. Data stored

    this way can provide insights and historical details about how those rows

    have changed over time.

    # Query for the latest data If you simply want the latest version of the objector objects, if you

    elected to track more than one during the setupin the integrations table

    (data), youll have to adjust your querying strategy to account for the

    append-only method of replication. This is a little different than querying

    records that are updated using updated_at incremental replication. To do this, you can use the _sdc_sequence column and the tables primary key.

    The _sdc_sequence is a Unix epoch (down to the millisecond) attached to the

    record during replication and can help determine the order of all the

    versions of a row.

    NOTE If you didnt define a primary key while setting up the integration,

    the primary key for the table will be _sdc_primary_key.

    If you want to create a snapshot of the latest version of this table, you

    could run a query like this: SELECT * FROM [stitch-redshift:stitch-iterable.data] o

    INNER JOIN (

    SELECT

    MAX(_sdc_sequence) AS seq,

    [primary-key]

    FROM [stitch-redshift:stitch-iterable.data]

    GROUP BY [primary-key]) oo

    ON o.[primary-key] = oo.[primary-key]

    AND o._sdc_sequence = oo.seq

    This approach uses a subquery to get a single list of every rows primary key

    and maximum sequence number. It then joins the original table to both the

    primary key and maximum sequence, which makes all other column values

    available for querying.

    # Schema In v1 of the stitch incoming webhooks integration, Stitch will create a

    single tablecalled datain the webhook integration schema (this will be

    the name you enter in the Integration Schema field when you set up Iterable)

    of your data warehouse. The schema of this table will contain two types of columns:

    Columns used by Stitch (prepended with _sdc) Columns sent by the providers webhook API

    Aside from the Stitch columns, the schema of this table will depend entirely

    on Iterables webhook API. With the exception of the _sdc fields, Stitch does

    not augment incoming webhooks data nor does it have any control over the

    fields sent by the webhook provider.

    # Webhook URLs & security Stitch allows you to generate up to two Iterable webhook URLs at a time. These

    URLs contain security access tokens and as such, have access to your Iterable

    account. If you ever need to change your webhook URL, you can do so in the

    Integration Settings page after the integration has been created:

    Click into the integration from the Stitch Dashboard page. Click the Settings button. In the Webhook URLs section, click the Generate Webhook URL button. A new webhook URL will display. Press the clipboard icon to copy it. Follow the steps in the

    section to update the webhook URL in Iterable.

    Afteryou'veupdated the webhook URL in Iterable, click the Revoke button

    next to the oldest webhook URL in Stitch. This will invalidate the token and

    revoke access.

    View Article
  • Iterable can ingest Zendesk

    webhooks to enable the automation of user profile updates and messaging

    campaigns based on user actions taken and tickets filed in Zendesk.

    NOTE This integration requires an Iterable account and a

    Zendesk account. If youre not already an Iterable client,

    request a demo

    to discuss how the Iterable and Zendesk integration can work for you.

    # Instructions You must have Zendesk admin access to set up this integration. Reference

    this Zendesk support doc

    for further help setting up the webhook in Zendesk.

    # Create an API key in Iterable

    Sign in to Iterable account at https://app.iterable.com/login/.

    Navigate to Integrations > API Keys. /events/track

    Click Create New API Key.

    For the key type, select JavaScriptSDK. Click Create. Copy the API key from the Key column of the Existing API Keys table.

    # Create a webhook in Zendesk

    NOTE This example demonstrates how to create a Zendesk webhook that will post an event to

    Iterable's /events/track

    endpoint. You can also use this method to update information on the user

    profile simply by mapping the webhook (or Notify Target, as Zendesk refers

    to it) to the /users/update

    endpoint.

    In Zendesk Support, click the Admin icon

    ()

    in the left sidebar. Then, select Settings > Extensions. Click the Targets tab and click Add Target.

    Select HTTP Target. You will be taken to a page similar to this

    screenshot:

    For the URL, enter the following: https://api.iterable.com/api/events/track?apiKey=[YOUR_API_KEY]

    For Method, choose POST. For Content type, choose JSON.

    Click Submit. You will be taken to a page where you can test a call to Iterables

    endpoint with your proposed JSON body. Please note that you need to

    structure the JSON body in accordance with the Iterable endpoint the

    Zendesk Webhook is pointing at. Please refer to Iterable's

    API docs

    for examples.

    In a new browser tab, open Business Rules > Triggers.

    Click Create New Trigger and set up your logic. It should look something like this:

    In the Actions section, map the trigger to the webhook you just

    created.

    For the first dropdown, select Notify Target. For the second dropdown, select Title of the webhook defined in

    step 3.

    Provide a JSON body.

    Format the JSON payload as specified by Iterable's

    API. The JSON body should look similar to the screenshot above, and

    must contain an email and eventName parameter.

    Add merge parameters (placeholders) directly in the JSON body as

    necessary. For a list of available placeholders, click on the

    View Available Placeholders link, which will bring up a list

    similar to the following:

    Example JSON body: {

    "email": "{{current_user.email}}",

    "eventName": "New Zendesk Ticket Created",

    "dataFields": {

    "Ticket_Id": "{{ticket.id}}",

    "Ticket_Description": "{{ticket.description}}",

    "Ticket_Priority": "{{ticket.priority}}"

    }

    }

    Copy the JSON body into the webhook configuration in the previous

    browser tab.

    Click Submit. If youdon'tget an error code, login to your Iterable account and check

    the event under the test users email you used. Onceyou'veconfirmed Iterable ingested the test event, confirm that the

    trigger is active.

    Your automated webhook from Zendesk to Iterable is now set up and you can use

    events ingested from Zendesk to trigger messaging campaigns.

    View Article
  • This document describes metadata stores, a way to save data in Iterable

    and use it to personalize message campaigns.

    IMPORTANT

    Iterable will sunset metadata store APIs and the #metadata Handlebars

    helper in favor of Catalog

    on March 10, 2020. Contact your Iterable CSM to discuss adding Catalog to

    your plan. For information about differences between Catalog and metadata stores,

    see Using Catalog.

    # Table of contents

    What is a metadata store?

    Do I need a metadata store?

    How do I set up a metadata store?

    How do I edit an existing metadata store?

    How do I use my metadata in an email template?

    What is the maximum size for a metadata store entry?

    Can I use a metadata store to store and insert HTML snippets?

    Further reading

    # What is a metadata store? A metadata store is a database of data fields that are common across your

    project. By using it, you can insert common fields into your messages

    without having to send them with event tracking API calls. For example, consider a food delivery service with a central list of

    restaurant information. This company might use the metadata store to

    look up and insert an individual restaurant's information into its

    emails, without having to pass along lots of data on event tracking

    API calls.

    # Do I need a metadata store? If you have a large amount of data that is common to all your users, and

    you're commonly referencing that data in your emails, you might want to

    consider setting up a metadata store. If you're unsure, feel free to

    email [email protected] for more information.

    # How do I set up a metadata store? Use the PUT /metadata/{table}/{key}

    API endpoint to add entries to a metadata store. Metadata stores save

    entries as key-value pairs (the keys being used to look up the

    data again in the future). When calling this API, the request body must have a value key

    associated with an object containing the item's details: {

    "value": {

    "field1": "ABC",

    "field2": "DEF"

    }

    }

    For example, the following API calls store data in a restaurants

    metadata store:

    Korean Restaurant

    URL: PUT /metadata/restaurants/koreanrestaurant

    Request body:{

    "value": {

    "name":"Korean Restaurant",

    "hours":"10am-2pm",

    "bestitem":"Galbi"

    }

    }

    Boba Place

    URL: PUT /metadata/restaurants/ilyasbobaplace

    Request body:{

    "value": {

    "name":"Ilya's Boba Place",

    "hours":"3pm-5am",

    "bestitem":"Green Tea Latte"

    }

    }

    Fancy Restaurant

    URL: PUT /metadata/restaurants/fancyrestaurant

    Request body:{

    "value": {

    "name":"Fancy Restaurant",

    "hours":"12pm-10pm",

    "bestitem":"Prix fixe"

    }

    }

    # How do I edit an existing metadata store? Update an existing metadata store using the

    PUT /metadata/{table}/{key}

    API endpoint. Include the entire object to ensure that all the unchanged

    fields are preserved. For example, to edit the hours of the Korean Restaurant defined

    above, include all of the restaurant's data fields, even though name

    and bestitem have not changed:

    URL: PUT /metadata/restaurants/koreanrestaurant

    Request body: {

    "value": {

    "name":"Korean Restaurant",

    "hours":"9am-3pm",

    "bestitem":"Galbi"

    }

    }

    ```

    # How do I use my metadata in an email template? Use Handlebars to insert data from a metadata store in a message template. For example, you might use a favRestaurant user profile field to look up

    a user's favorite restaurant in a restaurants metadata store, and then

    reference its bestItem: {{#metadata "restaurants" favRestaurant as |restaurantInfo|}}

    The restaurant's best item is {{restaurantInfo.bestitem}}

    {{else}}

    The restaurant's best item could not be found!

    {{/metadata}}

    Using the example data from above, a user whose favRestaurant is

    bobaPlace would see a message mentioning its Green Tea Latte. If the user profile doesn't have a favRestaurant value, or if the

    restaurants metadata store doesn't have a match for the profile's

    favRestaurant value, the message would instead display "The restaurant's

    best item could not be found!" To suppress the message instead of displaying alternative text, use the

    required=true attribute: {{#metadata "restaurants" favRestaurant required=true as |restaurantInfo|}}

    The restaurant's best item is {{restaurantInfo.bestitem}}

    {{/metadata}}

    # What is the maximum size for a metadata store entry? Each entry must be 30KB or less.

    # Can I use a metadata store to store and insert HTML snippets? Yes, with the caveat that each HTML snippet must be 30KB or less. Use the PUT /metadata/{table}/{key}

    to store the HTML snippet in the metadata store. Insert the snippet in

    the snippet into an email template using Handlebars logic.

    # Further reading

    Catalog Overview Using Catalog Catalog Items Defining Data Types for Catalog Item Fields Collections Using Collections in Messages Catalog Issues and Limitations Catalog APIs API Overview and Sample Payloads Metadata Store APIs

    View Article
  • support site Welcome to Iterable, your agile and user-friendly growth marketing platform

    that allows you to send the right message, to the right device, at the right

    time! We've created a list of useful shortcuts that will show you how to carry out

    your most important tasks.

    # What is your role at your company?

    Email Marketer Email Designer Integration Engineer Mobile Engineer Data Analyst

    # Common tasks

    # Setting up Iterable for the first time?

    Setting up a new Iterable project Set up user roles and permissions Add a new project Delete a project

    # Managing your customers?

    Import user lists Create a new list View a user profile

    # Creating or modifying an email campaign?

    Create a new blast campaign Schedule a recurring blast campaign Create a new triggered campaign Clone an existing campaign Archive an existing campaign Cancel, reschedule, or abort an existing campaign View the results of a completed campaign Create a new email template from scratch (no HTML experience)

    # Trying to set up more advanced campaign logic using workflows?

    Create a new workflow Troubleshoot a workflow Setup custom events in workflow

    # Creating a new template?

    Upload HTML file for email template (from PC/from website) Create a new email template from scratch (HTML experience) Sending push notifications Create a new SMS template Personalize a template with user data or event fields Personalize a template with data feed Create templates with multi-language support Preview a template with real user data or a data feed

    # Managing existing templates?

    Revert back to a previous version of a template View the history of changes for a template Clone an existing template

    # Setting up your tools to work with Iterable's API?

    View API documentation Create, edit, or delete API keys Create, edit, or delete webhooks Create, edit, or delete data feeds Setup custom event API calls Import user lists via API Add JS snippet to call Iterable API

    # Integrating Iterable with one of your existing platforms?

    Set up Mixpanel integration Set up Segment integration Set up mParticle integration Set up Magento integration Set up Zapier/SurveyMonkey integration Integrate with other services

    # Setting up mobile integrations?

    Set up iOS push notifications Set up Android push notifications Disable push notifications View API documentation Frequently Asked Questions Setup in-app messages

    # Performing data analysis?

    Set up an A/B experiment View the metrics of a completed campaign Understand email campaign metrics Understand SMS campaign metrics Understand push notification campaign metrics Understand A/B experiment analytics View the aggregated metrics for multiple campaigns Export campaign results Setup custom conversion tracking Track purchases and revenue

    # Other questions? Have more questions that aren't covered in the handbook? Check out our or contact our

    wonderful Customer Success team!

    View Article
  • This section will cover best practices around testing and troubleshooting

    your deep links. #

    # Table of contents

    Testing deep links

    Troubleshooting deep links

    Mail Domain is not verified

    Links are not rewritten

    Links are rewritten as /u instead of /a

    Universal links are not launching app

    # Testing deep links

    If the email deep link is clicked but it does not take you directly into

    the app (and instead you are directed to a mobile-web browser), please:

    Ensure the AASA file is properly formatted. This Branch tool should help. Ensure the AASA file is available at the end of your domain under: https://yourdomain/apple-app-site-association.

    Ensure Your file is served over HTTPS (not HTTP).

    Ensure the mobile app is configure to deep link in Xcode Capabilities. Re-download your provisioning profiles in Xcode.

    If the email deep link opens the app directly but not to the content you

    expected, please:

    Review your URL handing methods. Review your deep links schema

    # Troubleshooting deep links Below is an end-to-end schematic for Troubleshooting Deep Linking

    # Mail Domain is not verified Make sure you have secure protocol set up to comply with HSTS. Make sure you

    have added following while creating SSL certificate:

    Origin SSL Protocols: check only TLS1.2 Origin Protocol Policy: HTTPS Only

    Also Make sure you have added CNAME and A record to your domain's DNS Settings.

    # Links are not rewritten HTTPS is required for deep linking. Make sure you have enabled HTTPS in

    Project Settings > Main Domain > Tracking Domain.

    # Links are rewritten as /u instead of /a Enable Deep Link Rewriting in the Mobile Deep Linking section of

    project settings.

    Universal links are not launching app Make sure your app has associated domain set to launch the app. For iOS, add an associated whitelabel domain in Xcode, under

    Capabilities > Associated Domain. For Android, add <intent-filter> with <host> and <scheme>. <intent-filter android:autoVerify="true">

    <action android:name="android.intent.action.VIEW" />

    <category android:name="android.intent.category.DEFAULT" />

    <category android:name="android.intent.category.BROWSABLE" />

    <data android:host="links.iterable.com" android:pathPrefix="/a/" android:scheme="http"/>

    <data android:host="links.iterable.com" android:pathPrefix="/a/" android:scheme="https"/>

    <data android:host="demo-app.iterable.com" android:pathPrefix="/" android:scheme="https"/>

    </intent-filter>

    View Article
  • This section covers out integrations with partners to execute third-party

    deep linking within Iterable. This will enable you to track deep links within

    Iterable and with attribution partners.

    WARNING You must set up iOS and Android deep linking before these integrations

    will work. To do so, please read iOS Universal Links Setup and

    Android App Links Setup.

    Universal links allows you to automatically convert your email links into

    multi-platform deep links that take users directly to content in the app on

    mobile devices, while still maintaining the same web experience for desktop

    and mobile users without the app.

    # Table of contents

    Branch integration overview

    Set up your click tracking domain

    Branch installation

    Branch contact

    AppsFlyer integration overview

    AppsFlyer mobile setup

    Set up your click tracking domain

    AppsFlyer contact

    # Branch integration overview [email protected] Branch provides one of the leading cross-platform linking and

    attribution platform with solutions that unify user aquisition and

    measurement across different devices, operating systems, and channels.

    # Set up your click tracking domain Within Iterable, you must set up a custom click tracking domain. Add and verify a custom click tracking domain in the [Mail Domains] page of

    your Iterable account: After you added and verified a click tracking domain you have to update DNS

    CNAME for it and point it to thirdparty.bnc.lt. Once the CNAME record is

    added, please allow up to an hour for Branch to generate SSL and AASA files

    for your click tracking domain.

    # Branch installation Please review Branch Documentation

    to see the rest of the integration.

    # Branch contact [email protected]

    # AppsFlyer integration overview AppsFlyer is one of the leading attribution platforms and

    include a deep-linking solutions that measures attribution and acquisition

    across different devices, operating systems, and channels.

    # AppsFlyer mobile setup Please follow the guide on the AppsFlyer site

    and confirm your deep linking is working within their system before trying to

    integrate with Iterable.

    # Set up your click tracking domain Within Iterable, you must set up a custom click tracking domain. Add and verify a custom click tracking domain in the [Mail Domains] page of

    your Iterable account: After you added and verified a click tracking domain you have to update DNS

    CNAME for it and point it to *.onelink.com/ Once the CNAME record is added.

    # AppsFlyer contact

    View Article
  • Deferred deep linking allows a user to click on a link, install an app

    associated with the link, and then visit the content associated with that

    link in the newly installed app.

    WARNING To enable this feature, contact your Iterable CSM.

    #

    # Table of contents

    Overview

    iOS deferred deep linking

    Android deferred deep linking

    # Overview Deferred deep linking

    allows a user who does not have a specific app installed to:

    Click on a deep link that would normally open content in that app. Install the app from the App Store. Open the app and immediately see the content referenced by the link.

    As the name implies, the deep link is deferred until the app has been

    installed. After tapping a deep link in an email from an Iterable campaign, users

    without the associated app will be directed to the App Store to install it.

    If the app uses the Iterable iOS SDK and has deferred deep linking enabled,

    the content associated with the deep link will load on first launch.

    # iOS deferred deep linking Set IterableConfig.checkForDeferredDeeplink to true to enable deferred

    deep linking with the Iterable iOS SDK. This should be added to the

    beginning of your

    application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)

    method. Swift let config = IterableConfig()

    config.checkForDeferredDeeplink = true

    Android deferred deep linking In the Android SDK, call the setter method

    IterableApi.getInstance.setDDLChecked passing in true to enable deferred

    deep linking. This should be added to your Application class within the

    onCreate() method along with the other IterableApi initializations. Java IterableApi.getInstance().setDDLChecked(true);

    View Article
  • When you use iOS Universal Links in your messages, users who are using iOS 9

    and up can tap a link to your website and get seamlessly redirected to your

    installed app without going through a browser, all while having the links

    tracked within Iterable. #

    WARNING You must set up HTTPS link tracking before following the steps in

    this guide.

    # Table of contents

    Setup

    Example file

    FAQ

    What happens if a user doesn't have my app installed but clicks on a Universal Link?

    Will this work on Android too?

    Will this work for users on iOS versions lower than 9?

    Can I have more than one apple-app-site-association for my domain?

    Will this work for subdomains (cats.example.com) or only the top level domain (example.com)?

    What should an apple-app-site-association file look like? How does all this work?

    Can you illustrate the flow in a more graphical form?

    Can I use wildcards in my apple-app-site-association file?

    Do I need to include the Iterable appID section in my app-app-site-association file?

    # Setup

    Determine which links you want to redirect to your iOS application. Identify the target pages and their corresponding URLs that you want to

    send users to via Universal Links. For example, if you are a home browsing app, you may want /homes/

    schema to securely redirect all your users to the home browsing section.

    Create an apple-app-site-association file. Once you have determined which URLs to link to, create an

    apple-app-site-association file that will contain the redirect rules

    to the URLs you have identified in step 1. This file is a JSON object

    that determines which links to rewrite into Universal Links. Below is a sample one you can use. The file name does not matter but it

    must be a JSON file. You can read more about creating apple-app-site-association files in

    Apple's developer documentation. Iterable will use your apple-app-site-association file to determine

    which links in your messages to rewrite into iOS Universal Links.

    NOTE After the links have been rewritten by Iterable, they will appear in this

    format:

    Normal track and redirect URLs:

    mydomain.com/u/samplepath

    iOS Universal Links:

    mydomain.com/a/samplepath

    # Example file {

    "applinks": {

    "apps": [],

    "details": [

    {

    // The App Id is found on the apple developer account

    // the bundle ID is found in Xcode General section

    "appID": "appID.bundleID",

    "paths": [

    //The /a/* is all you need here

    "/a/*"

    ]

    },

    {

    "appID": "iterable",

    "paths": [

    //PATHS TO BE REDIRECTED GO HERE

    //For Example: This is your path to show a product

    "/product/*",

    //This maybe to show your credentials page

    "/credentials/*"

    //This would prevent a deep link to a certain section

    "NOT /email-confirmation/*",

    ]

    }

    ]

    }

    }

    Email your apple-app-site-association file to [email protected]. After we process the file, you can view it on the bottom of the

    project settings screen (Settings > Project Settings).

    Set up your iOS application to handle Universal Links

    Add your whitelabeled domain (for example,

    links.YOUR_COMPANY_NAME.com) to the Associated Domain in your Xcode

    Capabilities. You can read more about it in

    Apple's developer documentation.

    You also need to whitelabel your account by updating your CNAME record

    to point to Iterable, under Settings > DNS Setup. For more

    information on updating your DNS records, read

    Sending Your First Campaign.

    Next, From your application's restorationHandler,

    call the getAndTrack on IterableApi, along with a callback to handle

    the returned original URL to deep link to the appropriate page.

    IterableSDK (4.3.0+):

    Swift: func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {

    guard let url = userActivity.webpageURL else {

    return false

    }

    // This will track the click, retrieve the original URL and call `handleIterableURL:context:` with the original URL

    return IterableAPI.handle(universalLink: url)

    }

    Objective-C: - (BOOL)application:(UIApplication *)application continueUserActivity(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {

    // This will track the click, retrieve the original URL and call `handleIterableURL:context:` with the original URL

    return [IterableAPI handleUniversalLink:userActivity.webpageURL];

    }

    Without the SDK: Add this code snippet

    to your continueUserActivity instead of calling the SDK's built-in

    getAndTrackDeeplink function.

    NOTE The apple-app-site-association file is obtained when the app is

    installed or updated, so you'll need to release a new version of the

    app before all your existing users see the new path.

    Here is some sample code that shows how you can handle Universal

    Links within your app: func application(_ application: UIApplication, continue userActivity: NSUserActivity,

    restorationHandler: @escaping ([Any]?) -> Void) -> Bool {

    print("Clicked on link: \(userActivity.webpageURL?.absoluteString)")

    IterableAPI.getAndTrackDeeplink(userActivity.webpageURL!, callbackBlock: {

    (url) in

    print("Handle Original URL deep link: \(url)");

    });

    return true

    }

    Set up HTTPS for your links domain Follow the instructions here

    to set up HTTPS for your domain so that your AASA file is correctly read.

    Set up your website to handle Universal Links Ensure that your website is set up to handle Universal Links, so that

    users who do not have an app set up for Universal Links will get

    gracefully redirected to the corresponding link on your website. We recommend that you mirror your iOS and website paths in order to

    improve maintainability of the redirection logic over time.

    Congratulations, you are now ready to test your iOS Universal Links!

    # FAQ

    # What happens if a user doesn't have my app installed but clicks on a Universal Link? The user will get directed to your website in his/her browser like a normal

    link, as long as your website has been set up to handle Universal Links (see

    step 5 above).

    # Will this work on Android too? Yes! Please go to the next section titled Android App Links Setup.

    # Will this work for users on iOS versions lower than 9? Unfortunately, iOS 9 is the minimum requirement for Universal Links to work

    on the user's device.

    # Can I have more than one apple-app-site-association for my domain? Each domain can only have a single apple-app-site-association file.

    # Will this work for subdomains (cats.example.com) or only the top level domain (example.com)? We now rewrite URLs for subdomains as well as top-level domains.

    # What should an apple-app-site-association file look like? How does all this work? Here's a sample apple-app-site-association file that we will use to walk

    through the entire process: {

    "applinks": {

    "apps": [],

    "details": [

    {

    "appID": "appID.bundleID", <-- Add Your AppId from Itunes Connect and Bundle ID from Apple developer site

    "paths": [

    "/a/*" <-- [RULE 1] Mandatory rule required in all Iterable association files

    ]

    },

    {

    "appID": "iterable", <-- Add Your AppId from Itunes Connect

    "paths": [

    "NOT /samplepath/toignore", <-- [RULE 2] Tells Iterable to write as regular (non-Universal) link

    "/samplepath/*" <-- [RULE 3] Tells Iterable to rewrite into Universal Path

    ]

    }

    ]

    }

    }

    WARNING Only edit the content with notes next to it.

    When you send that file to Iterable, we store a copy of it on our servers.

    When you send a message, the following happens:

    Iterable goes through each link in the message and compares it to the list

    of rules in the apple-app-site-association file to see if there is a

    match. For this example, let's assume that one of your links is

    yourdomain.com/samplepath/hello.html. If there is a match, Iterable will rewrite the link before sending it out

    in your message. In this example, yourdomain.com/samplepath/hello.html

    matches RULE 3 above and will be rewritten into

    yourdomain.com/a/ABCD1234, where ABCD1234 is a unique identifier for that

    link (you don't have to worry about this unique identifier). At this point, Iterable also stores a mapping of /a/ABCD1234 to

    /samplepath/hello.html on the Iterable servers. When a user clicks on the rewritten link /a/ABCD1234, the user's device

    will detect it based on RULE 1 in the apple-app-site-association file (a

    copy of the file is stored on device) and opens your app based on the appID

    in the file. Your app then uses the Iterable SDK to make a call to Iterable's servers

    to track the click and get the actual destination /samplepath/hello.html. Your app receives /samplepath/hello.html from the Iterable server and

    opens the destination within your app.

    # Can you illustrate the flow in a more graphical form? Sure thing! Here's a similar example for iOS Universal Links to the

    snapface.com domain.

    # Can I use wildcards in my apple-app-site-association file? Yes, you can use * to specify an entire section (matches all substrings) or ?

    to match any single character. You can combine both wildcards in a single

    path, such as /foo/*/bar/201?/mypage which would match

    /foo/abc/bar/2015/mypage and /foo/def/bar/2019/mypage. For more details, check out Apple's documentation here.

    Do I need to include the Iterable appID section in my app-app-site-association file? Yes. The purpose of the Iterable appID section is to provide more control

    over which paths get rewritten by Iterable. If you want a subset of paths to

    be opened in Iterable but not the others, then placing those paths under the

    Iterable appID section will limit rewriting to those paths. If you want all paths to be rewritten, use: {

    "appID": "iterable",

    "paths": ["*"]

    }

    View Article
  • # Table of contents

    Overview

    Testing

    1. Navigate to Contact Lookup

    2. Look up your specific user

    Troubleshooting

    User profile not found in iterable

    Update user profile is failing

    dataTypeMismatch while updating user profile

    Invalid API key

    Error:4XX email already exists

    Duplicate users in Iterable

    # Overview Typically it is fairly easy to troubleshoot the User Profile within Iterable.

    You will just want to ensure that the correct userId or email has the

    most up to date information from your testing. You can view individual user

    profiles in Iterable by going to Audiences > Contact Lookup Section as

    shown below.

    NOTES

    You can store a soft limit of 1,000 user parameters on your user profiles If you are only identifying the user on the IterableAPI.userId call, then

    Iterable assumes you do not know the email of the user yet and will create a

    placeholder email called [email protected]. We will

    discuss in the next section how we can update the email of an unkown user.

    You will also want to confirm:

    You are using the correct userId or email. You do not have any duplicate IterableAPI.email = "[email protected]" calls. You have the correct API key for that project. That API key has userUpdate priviledges.

    # Testing To verify is the user profile is being generated and set with relevant

    information, go to Audience > Contact Lookup > Enter Test Email Address

    and search. This should return a user profile with email address and userId

    (if set).

    # 1. Navigate to Contact Lookup #

    # 2. Look up your specific user

    # Troubleshooting

    # User profile not found in iterable

    Make sure you are looking in the correct project, user profiles created

    and updated with sandbox project won't appear in productions and vice versa. Make sure you are setting an email after Iterable SDK is initiated.

    # Update user profile is failing We recommend using email id as primary key when updating user's profile. If

    you use userId as a primary key to update user'r profile, you may run into

    duplicate record error.

    # dataTypeMismatch while updating user profile This error occurs when you pass a differnt data format for an existing field.

    Make sure all your data formats match when making update user profile call.

    # Invalid API key Verify your API key is valid. Make sure you are using a mobile API key or

    standard API key in the app.

    # Error:4XX email already exists If you are updating existing user with new known email address, make sure you

    are using 'merge': true in the request. This will merge new data with

    existing user without trying to create or override existing user fields.

    Duplicate users in Iterable This can happen when apps aren't synchronized with updated user profile. When

    a user updates their email address on web app, this will update a current

    user with with an updated email address. If user's mobile app is not

    sychronized to get updated user profile, when user accesses mobile app later,

    register device token can create a new user with old email address. Make sure you are not calling register device token method on outdated email

    address.

    View Article
  • Below are some recommended (but optional) additions to your user update

    mobile code.

    # Table of contents

    Attribution on user profile

    User logout and endpointEnabled

    endpointEnabled Why will a token be set as invalid?

    Session counter best practices

    Hiding user properties

    NOTES Don't feel like you need to integrate this section unless these use cases are

    relevant to your business.

    # Attribution on user profile You can attach third-party attribution data to the user profile to leverage

    in your own campaign. For example, if you know a user came from an

    advertisement campaign for benefits over your competitors, you may want to

    leverage those features in a push campaign. Each mobile attribution provider has their client-side methods for returning

    attribution data at time of the app launch. Below are some top mobile

    attribution and links to their documentation for returning attribution data.

    AppsFlyer Branch Adjust

    You can attach the response of these methods to the Iterable User Profile and

    leverage those results in your owned media.

    # User logout and endpointEnabled When the user logs out of your app, you also want to make sure you disable

    the user from receiving push notifications for the previous user. You will

    want to call the method below when your user logs out. Swift disableDeviceForCurrentUser()

    Java IterableApi.getInstance().disablePush();

    # endpointEnabled Device tokens are required to communicate with specific devices. When a

    mobile platform (such as APNS or GCM) informs that token is invalid, we set

    endpointEnabled to false.

    # Why will a token be set as invalid? A token can be set invalid by any of the following:

    When disableRegistrationToken has been called explicitly. While using SDK, if app doesnt set autoPushRegistration to false. When

    autoPushRegistration is set to true SDK automatically enables and

    disables the token. When app is uninstalled.

    # Session counter best practices The best methodology for tracking sessions is to add a counter client-side

    and then update the user profile on each subsequent app launch.

    NOTES You will likely not want to include Sessions as an Iterable Track Call

    because sessions typically occur 20x-40x more than any other event! This

    flooding of events will create a lot of noise and make it difficult to

    navigate towards signaling events.

    Navigate to the AppDelegate file in your Xcode and add this code to your applicationDidBecomeActive: Swift func applicationDidBecomeActive(_ application: UIApplication) {

    // get current number of times app has been launched

    let currentCount = UserDefaults.standard.integer(forKey: "launchCount")

    // increment received number by one

    UserDefaults.standard.set(currentCount+1, forKey:"launchCount")

    // return counter

    let iter_session_counter = UserDefaults.standard.integer(forKey: "launchCount")

    IterableAPI.updateUser(["iter_current_app_session_counter":iter_session_counter], mergeNestedObjects: false, onSuccess: myUserUpdateSuccessHandler, onFailure: myUserUpdateFailureHandler)

    }

    # Hiding user properties Sometimes people make mistakes and you may accidentally record a user

    property wrong within your Iterable production instance (yikes!). There is

    however an easy fix to hide unnecessary data. Navigate to the

    Project Settings of your Iterable project and scroll down to the

    User Properties listings. You can select which User Properties you'd like to view in your project,

    which will hopefully save your team a lot time and effort. For more

    information, please checkout our Project Settings documentation.

    View Article
  • Updating the User Profile reflects the most recent information about a user.

    User Profile data enables you to:

    Populate any Iterable channel (Email, Inapp, Push, SMS, etc..) with

    personalized information later with Handlebars

    Flag users for A/B testing, cohorting and Segmentation Start a user journey

    A user profile value can be a value like first name, or a dynamic value that

    changes, such as the date of last login or the number of times the user

    purchases a food.

    # Table of contents

    How to make the updateUser call

    When to make the updateUser call

    NOTES

    You can store a soft limit of 1,000 user parameters on your user

    profiles. If you feel you may go over this, please reach out to your Iterable

    point of contact and request it to be raised. Again, if you are only identifying the user on the IterableAPI.userId

    call, then Iterable assumes you do not know the email of the user yet and

    will create a placeholder email called [email protected].

    We will discuss in the next section how we can update the email of an unkown

    user.

    # How to make the updateUser call Iterable can handle multi-level deep nested objects. You will want to add

    that object to the dataField arguement in the IterableAPI.updateUser()

    user call. Swift // The IterableAPI.updateUser() can be added any method within your code. myFunc() is just an example

    myFunc(){

    // Example data fields

    let dataField : [String: Any] = [

    "Address":[

    "Street1": "123 Main St",

    "Street2": "Apt 1",

    "City": "Iter-a-ville",

    "State": "Ca",

    "Zip": "90210"

    ]

    ]

    // Most important code

    IterableAPI.updateUser(dataField, mergeNestedObjects: false, onSuccess: myUserUpdateSuccessHandler, onFailure: myUserUpdateFailureHandler)

    }

    func myUserUpdateSuccessHandler(data:[AnyHashable:Any]?) -> () {

    // success

    print("sent to Iterable success")

    }

    func myUserUpdateFailureHandler(reason:String?, data:Data?) -> () {

    // failure

    print("sent to Iterable failure")

    }

    Java JSONObject address = new JSONObject();

    JSONObject datafields = new JSONObject();

    try {

    address.put("Street1", "123 Main St");

    address.put("Street2", "Apt 1");

    address.put("City", "Iter-a-ville");

    address.put("State", "CA");

    address.put("Zip", "90210");

    datafields.put("dataFields", address);

    } catch (JSONException e) {

    e.printStackTrace();

    }

    IterableApi.getInstance().updateUser(datafields);

    Now you will be able to personalize the user's City (or any user profile)

    later with Handlebars

    in any of your channels by writing this code within the Iterable platform: {{Address.City}}

    NOTES

    mergeNestedObjects default is set to false

    mergeNestedObjects set to true means that if the user profile has data:

    {mySettings:{mobile:true}} and your code changes the contact field to:

    {mySettings:{email:true}}, the resulting profile will be:

    {mySettings:{mobile:true,email:true}} and merge the two results.

    # When to make the updateUser call Typically you want to make the updateUser() call when:

    Your user has changed or added their personal information Completed a key step in your onboarding, sales or retargeting process. For

    example, you may want to add "completedOnboarding":true or

    "testGroup":"A" to the user profile for later segmentation, splitting the

    users down different journeys or analyzing later for test comparisons.

    # Tracking anonymous users Iterable can track anonymous users by utilizing the userId. This will

    automatically create a placeholder email. You can use a variety of client

    side libraries to generate a unique ID on demand and pass it to the Iterable

    userId parameter.

    # Taking a user from anonymous to known Iterable can handle anonymous to known users. The function below will update

    the current user email and userId. You will likely want to call the code

    below when your user logs in or identifies themselve via a signup. Swift // The IterableAPI.updateUser() can be added any method within your code. yourUserIsNowKnownFunction() is just an example

    let email = "[email protected]"

    //Call

    yourUserIsNowKnownFunction() {

    IterableAPI.updateEmail(email, onSuccess: myUserUpdateSuccessHandler, onFailure: myUserUpdateFailureHandler)

    }

    func myUserUpdateSuccessHandler(data:[AnyHashable:Any]?) -> () {

    // success

    print("sent to Iterable success")

    }

    func myUserUpdateFailureHandler(reason:String?, data:Data?) -> () {

    // failure

    print("sent to Iterable failure")

    IterableAPI.email = email

    //This assumes your saving your user profile fields in the datafield object locally

    IterableAPI.updateUser(dataField, mergeNestedObjects: false)

    }

    Java final String email = "[email protected]";

    IterableApi.getInstance().updateEmail(email, new IterableHelper.SuccessHandler() {

    @Override

    public void onSuccess(JSONObject data) {

    System.out.println("sent to Iterable success");

    }

    }, new IterableHelper.FailureHandler() {

    @Override

    public void onFailure(String reason, JSONObject data) {

    System.out.println("sent to Iterable failure");

    IterableApi.getInstance().setEmail(email);

    //This assumes your saving your user profile fields in the datafield object locally

    IterableApi.getInstance().updateUser(datafields);

    }

    });

    There is a chance the updateEmail() call will fail. The most likely reason

    is that the user already exists so we should now update the user call

    directly in the onFailure handler.

    View Article
  • The Iterable Android SDK is a Java implementation of an Android client for Iterable. Identifying the User

    SDK Support The Iterable Android SDK supports Android API versions 15 and higher

    ( Android version history ).

    # Table of contents

    Installing the SDK

    Initialize the SDK Configure

    Troubleshooting

    Next Steps

    # Installing the SDK

    Add Iterable Android SDK in your project Add Firebase Messaging Service support for your project

    To add Iterable SDK and Firebase messaging in your project, add the following

    dependencies to your application's build.gradle in dependencies block:

    dependencies{

    implementation 'com.iterable:iterableapi:3.1.3'

    implementation 'com.google.firebase:firebase-messaging:X.X.X' // Min version 17.4.0 this is required for push notifications and in-app messaging features

    }

    See Bintray for the

    latest version of the Iterable Android SDK.

    # Initialize the SDK

    # Configure In the onCreate method of the Application, initialize the Iterable SDK: IterableConfig config = new IterableConfig.Builder()

    .setPushIntegrationName("myPushIntegration")

    .build();

    IterableApi.initialize(context, "<your-api-key>", config);

    The apiKey should correspond to the API key of your project in Iterable. If

    you'd like, you can specify a different apiKey depending on whether you're

    building in DEBUG or PRODUCTION, and point the SDK to the relevant

    Iterable project.

    NOTES

    Don't call IterableApi.initialize from Activity#onCreate; it is

    necessary for Iterable SDK to be initialized when the application is

    starting, to make sure everything is set up regardless of whether the app is

    launched to open an activity or is woken up in background as a result of an

    incoming push message. You add your push notification integration in this step but we'll complete

    this in a later section which can be found here

    Once you know the email (Preferred) or userId of the user, call setEmail or setUserId

    EMAIL: IterableApi.getInstance().setEmail("[email protected]");

    USERID: IterableApi.getInstance().setUserId("userId");

    NOTE Don't specify both email and userId in the same session, as

    they will be treated as different users by the SDK. Only use one type of

    identifier, email or userId, to identify the user.

    # Multiple push providers To learn how to work with multiple push notification providers, read

    Setting up Android Push Notifications.

    # Troubleshooting If you're having trouble installing or initializing the SDK, read

    Testing and Troubleshooting the Iterable SDK.

    # Next Steps After the SDK has been installed, read .

    View Article
  • Apple and FCM require quite a few steps to set up push notifications. Below

    are some best practices on testing and troubleshooting Iterable push

    notifications. #

    # Table of contents

    Testing iOS push notifications

    Sending a test iOS push notification

    Getting the push notification token

    Troubleshooting

    Test push on Iterable is not working on iOS

    Invalid Token

    Invalid Sandbox .p12

    Invalid Production .p12

    Invalid bundle identifier

    Iterable sends the push notification, but the iOS device doesn't receive it

    Rich push is not working

    Push sent from a template is failing

    iOS 10 push notifications not registering

    Testing Android push notifications Sending a test Android push notification

    Android Troubleshooting

    Unable to create mobile push integration

    Test notification is not working on Android

    Iterable sends the push notification, but the Android device doesn't receive it

    # Testing iOS push notifications It is difficult to know exactly what is wrong and occasionally, you will have

    to repeat the steps from the beginning to know exactly what is wrong. Below

    are some steps and milestones for setting up push notifications.

    # Sending a test iOS push notification Once your certificate has been exported from Apple and uploaded to Iterable,

    you will want to send a test push via our Test Push Integration. To send a test

    push, go to Mobile Apps > Integrations > Test Push. Use the Apple Sandbox Certificates for Xcode and the

    Apple Production Certificates when testing from TestFlight.

    # Getting the push notification token You can get the push notification token directly from Xcode. To do so, use

    the code below to grab the printed deviceTokenString from the

    didRegisterForRemoteNotificationsWithDeviceToken. Then add that token to

    the above screenshot to send a Test Push to your device.

    NOTES It may take a little time for the certificate to propogate through the system

    so the first push may take a few minutes but then it should work as expected.

    Swift import Foundation

    //put outside class

    extension Data {

    var hexString: String {

    let hexString = map { String(format: "%02.2hhx", $0) }.joined()

    return hexString

    }

    }

    //usage

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    let deviceTokenString = deviceToken.hexString

    print(deviceTokenString)

    }

    # Troubleshooting

    # Test push on Iterable is not working on iOS If push on Iterable is not set up correctly, you would see one of the

    following errors on 'Test Push'.

    # Invalid Token Make sure the token you are using to test push set up belongs to correct

    bundle id configured for the setting. For APNS_SANDBOX testing, please use a

    token generated by sandbox app. Similarly, for production use the token

    generated with production push certificate.

    NOTE If you deploy your sandbox app to TestFlight, it uses production certificate

    and hence it should be tested using production set up instead on sandbox/dev

    set up.

    # Invalid Sandbox .p12 This error means you are uploading production .p12 file into a sandbox

    congifuration. Verify the .p12 file. If it is still failing, regerate the

    certificate and upload a newely exported dev .p12

    # Invalid Production .p12 This error means you are uploading sandbox .p12 file into a production

    configuration. Verify the .p12 file. If it is still failing, regerate the

    certificate and upload a newely exported production .p12 Apple now has an option of creating one certificate with production and

    sandbox extension. In your Apple Developer Account, while creating

    certificates, look for the Apple Push Notification service SSL (Sandbox & Production)

    option. This will make token management easier.

    # Invalid bundle identifier While uploading .p12 into Iterable platform, make sure you are uploading a

    relevant file for the bundle id specified. You may recieve an error shown

    above if the bundle identifier on .p12 doesn't match the bundle identifier

    mentioned in the set up.

    # Iterable sends the push notification, but the iOS device doesn't receive it Make sure your app has the user's permission to send a push notification. If you do not receive a test push, then unfortunately your certificates will

    likely need to be re-exported (Apple occasionally has this problem). Please

    follow the steps from the beginning.

    NOTE To test iOS push notifications, you must use a real device. You cannot use

    the iOS simulator.

    Before you start testing with push templates, verify if your device is

    registered under user's profile. Push template can be tested using user's

    email address. This will fetch device from devices array on user's profile

    and use the valid device token to send push to a user. Now test send a test push notification. Navigate to

    Templates > Push > Send Proof and click the Send Proof button, found

    in the lower-right corner. Send the message to the test email that you've set

    in the app. If the device receives your message, you are ready to send campaigns. If you do not receive the message but are receiving test pushes in step 2,

    check that the code in your app is identifying the email address that you

    sent the proof to. IterableAPI.email = "[email protected]"

    # Rich push is not working

    Make sure your system notifications are working, if not, please follow

    troubleshooting steps above. For rich push notification to work, you will need to make sure you have

    added IterableNotificationExtension to your Xcode project. Please follow this

    document on how to add extension.

    # Push sent from a template is failing There are multiple reasons why your push template proof is not working when

    test push is working.

    Make sure email address you are testing with has a devices array on their

    user's profile. If you are having trouble registering device on user's

    profile, please refer to user registration troubleshooting guide. Check if notificationsEnabled is set to true. notificationsEnabled is set

    to false when user disables permission to receive push notification. Check if endpointEnabled is set to true. endpointEnabled is set to false,

    if user uninstalls the app, making device token no longer valid for push.

    # iOS 10 push notifications not registering With the introduction of iOS 10 and Xcode 8, and there are a number of

    changes made to push notifications. In particular, note the following change to the aps-environment

    entitlement: Scenario: If you upgrade to iOS 10 and Xcode 8, and push notifications don't

    work, check to see if there are errors from didFailToRegisterForRemoteNotificationsWithError.

    If you get the following error on iOS 10 but not iOS 9, you will need to

    enable push entitlements locally. fail to register with error Error Domain=NSCocoaErrorDomain Code=3000 "no

    valid 'aps-environment' entitlement string found for application"

    UserInfo={NSLocalizedDescription=no valid 'aps-environment' entitlement

    string found for application}

    With Xcode 8, the entitlements are set from your local entitlements file,

    rather than from the provisioning profile you created on the Apple Developer

    Portal. The entitlements will now need to be added to your Xcode build under

    Capabilities, in addition to in your provisioning profile.

    # Testing Android push notifications To verify Android set up, go to Firebase Console.

    Send a test message from Cloud Messaging in Firebase to test your set up.

    # Sending a test Android push notification After you have verified the Firebase setup:

    Open the Iterable App

    Open up your your project. Click on Settings and open Mobile Apps. Click on the Android App and make sure the Firebase API key has been

    configured. Click on Test Push and enter the device token for your test device. Add a test payload and send the test.

    # Android Troubleshooting

    # Unable to create mobile push integration Make sure you have a correct API Key from Firebase. You can locate this key

    by opening your Firebase project and navigating to

    Settings > Project Settings > Cloud Messaging and looking in the

    Project Credentials section.

    # Test notification is not working on Android

    Make sure you have followed Firebase Set up and test from Firebase works.

    Check Firebase Setup

    for details. Verify the device token you are entering is correct

    Iterable sends the push notification, but the Android device doesn't receive it All push from Iterable platform are received as data messages in the app.

    Iterable SDK renders the notification. Thus, make sure you do NOT have 'OS

    Notifications' enabled when using Iterable SDK integration. Also make sure

    your app has user's permission to send push.

    View Article
  • Iterable System Webhook Iterable campaigns can send iOS push notifications. Push notifications are

    remotely triggered notifications that appear on a user's device even when

    the application is closed (depending on whether or not the user allows them). Users can then tap on these notifications to open the associated application

    to specific, relevant content or instant Action Buttons. If you are a marketer, work with your mobile engineers to implement the steps

    discussed in this article. If you have already completed the technical setup,

    learn more about setting up a push notification campaign by reading

    Creating a Push Notification Campaign. The Iterable SDK will facilitate:

    Passing of device tokens between Iterable and the App Passing images and gifs through as part of the push template Creating Action Buttons

    for your users to take instant actions from the push message. Tracking of:

    Push Bounce Push Open Push Send Push Send Skip Push Uninstall

    NOTES All the analytic data is available for free via the Iterable Export API

    or the

    features.

    View Article
  • Iterable can send push notifications to iOS and Android devices. Push

    notifications display content such as text and images, and can alert users by

    playing a sound. Depending on a user's device settings, push notifications can appear even

    when an application is closed. Upon receipt, users can tap these

    notifications to open the associated application or perform another action

    associated with the notification. Read Google's Notifications Overview

    document for technical information about push notifications on Android. This guide describes the technical setup necessary to send Android push

    notifications with Iterable. Work with your organization's mobile engineers

    to complete the steps below.

    # Table of contents

    Overview

    Instructions

    1. Set up Firebase for your Android app

    2. Create a mobile app in Iterable

    3. Assign a push integration to the mobile app

    4. Install Iterable's Android SDK in your mobile app

    5. Configure the SDK

    6. Use Iterable to send a test Android push notification

    Upgrading from Google Cloud Messaging (GCM) to Firebase Cloud Messaging (FCM)

    Customizing Android push notifications

    Adding sounds to Android push notifications

    Adding deep links to Android push notifications

    Setting the background color of a push notification

    Add custom icons to your push notifications

    Further reading

    # Overview To use Iterable to send push notifications to an Android app, the following

    things must happen:

    Your users must install your mobile app. Your mobile app must store a unique Firebase token on the user's

    Iterable profile. Iterable must contact Firebase, telling it what content to send and which

    devices to send it to.

    The Iterable Android SDK

    automatically tracks push notification opens. Alternatively, you can track

    push notification opens with Iterable's POST /api/events/trackPushOpen

    API.

    # Instructions Follow the steps below to set up Iterable to send Android push notifications:

    # 1. Set up Firebase for your Android app For Iterable to send Android push notifications, it must communicate

    with Firebase Cloud Messaging. To learn how to set up Firebase for your Android app, read Google's

    Add Firebase to your Android project

    document.

    # 2. Create a mobile app in Iterable Iterable uses mobile apps to store the details about your app's name,

    identifier, platform, and store URL.

    TIPS

    It's best to use separate Iterable projects for sandbox and production

    data. An Iterable push notification campaign can target as many (or few) of your

    mobile apps as necessary.

    To create a mobile app in Iterable:

    Navigate to Settings > Mobile Apps.

    Click Add a New Mobile App to bring up the Create New Mobile App

    form: Iterable Android SDK docs

    For Name, enter the name of your app. For example, Iterable Docs Push.

    For Platform, select Android.

    For Package Name, enter your application ID. For example, com.iterable.docspush.

    (Optional) For Store URL, enter your app's Play Store URL.

    Click Create App. This brings up a screen showing the app's details:

    # 3. Assign a push integration to the mobile app A push integration stores the API key Iterable uses to authenticate with

    Firebase when sending push notifications on your behalf. A push integration

    is stored as part of a mobile app. You can either associate an

    existing push integration or a

    new push integration with a mobile app.

    # Existing push integration To associate an already-existing push integration with the newly created

    mobile app:

    Navigate to Settings > Mobile Apps.

    Find the existing push integration in the Unassigned Integrations

    interface at the bottom of the screen.

    Click that push integration's Assign App button.

    In the Assign Push Integration window, select the mobile app you just

    created.

    Click Assign.

    # New push integration To create a new push integration for the mobile app:

    With the new mobile app still open in Iterable, click the Configure

    button next to Firebase, bringing up a window similar to the following:

    Select whether or not to Use OS Notifications.

    Enabling this option causes Android (instead of Iterable's SDK) to

    render push notifications for the app. Disabling this option causes the Iterable SDK to render push

    notifications for the app.

    WARNING It's usually best to leave this option disabled unless you are not using

    the Iterable Android SDK

    (or have another compelling reason to enable it).

    For API Key, enter your Firebase Server Key. Locate this key by opening your Firebase project and navigating to

    Settings > Project Settings > Cloud Messaging and looking in the

    Project Credentials section.

    Click Update to save the push integration.

    # 4. Install Iterable's Android SDK in your mobile app To install Iterable's Android SDK, follow the

    Installing the SDK

    instructions (on GitHub).

    NOTE You can receive Iterable push notifications without setting up the Android

    SDK. To do so:

    Set up your Android app as described in Google's

    Set up a Firebase Cloud Messaging client app on Android document. Call POST /api/users/registerDeviceToken

    each time the app opens. Call POST /api/users/disableDevice

    each time the user signs out of the app Track push notification opens by calling POST /api/events/trackPushOpen.

    # 5. Configure the SDK

    # Handling Firebase push messages and tokens The SDK adds a FirebaseMessagingService to the app manifest automatically,

    so you don't have to do any extra setup to handle incoming push messages. If your application implements its own FirebaseMessagingService, make sure

    you forward onMessageReceived and onNewToken calls to

    IterableFirebaseMessagingService.handleMessageReceived and

    IterableFirebaseMessagingService.handleTokenRefresh, respectively: public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override

    public void onMessageReceived(RemoteMessage remoteMessage) {

    IterableFirebaseMessagingService.handleMessageReceived(this, remoteMessage);

    }

    @Override

    public void onNewToken(String s) {

    IterableFirebaseMessagingService.handleTokenRefresh();

    }

    }

    IMPORTANT The step above is mandatory for handling multiple push providers.

    Note that FirebaseInstanceIdService is deprecated and replaced with

    onNewToken in recent versions of Firebase.

    # Push notifications

    In the onCreate method of the Application, initialize the Iterable SDK: IterableConfig config = new IterableConfig.Builder()

    .setPushIntegrationName("myPushIntegration")

    .build();

    IterableApi.initialize(context, "<your-api-key>", config);

    The apiKey should correspond to the API key of your project in

    Iterable. If you'd like, you can specify a different apiKey depending

    on whether you're building in DEBUG or PRODUCTION, and point the SDK

    to the relevant Iterable project.

    IMPORTANT Don't call IterableApi.initialize from Activity#onCreate; it is

    necessary for Iterable SDK to be initialized when the application is

    starting, to make sure everything is set up regardless of whether the app

    is launched to open an activity or is woken up in background as a result

    of an incoming push message.

    Once you know the email (Preferred) or userId of the user, call

    setEmail or setUserId

    EMAIL: IterableApi.getInstance().setEmail("[email protected]");

    USERID: IterableApi.getInstance().setUserId("userId");

    IMPORTANT Don't specify both email and userId in the same session, as they will be

    treated as different users by the SDK. Only use one type of identifier,

    email or userId, to identify the user.

    Register for remote notifications On application launch (or whenever you want to register the token), call

    registerForPush: IterableApi.getInstance().registerForPush();

    This will take care of retrieving the token and registering it with

    Iterable.

    IMPORTANT Device registration will fail if user email or userId is not set. If

    you're calling setEmail or setUserId after the app is launched (i.e.

    when the user logs in), make sure you call registerForPush() again to

    register the device with the logged in user.

    You can now send remote push notifications to your device from Iterable.

    # Disabling push notifications to a device When a user logs out, you typically want to disable push notifications to

    that user/device. This can be accomplished by calling disablePush(). Please

    note that it will only attempt to disable the device if you have previously

    called registerForPush(). In order to re-enable push notifcations to that device, simply call

    registerForPush() as usual when the user logs back in.

    # 6. Use Iterable to send a test Android push notification To send a test Android push notification, first look up the device token for

    a test user who has installed and run the app:

    In Iterable, navigate to Audience > Contact Lookup and enter the user's

    email address. In the devices array, examine the appPackageName field to find the

    object that corresponds to your app. Copy the token, since you'll need this to send the test push

    notification.

    Then, send a test push notification to that user:

    Navigate to Settings > Mobile Apps. Click the mobile app for which you'd like to send a push notification.

    In the Integrations section, click Test Push to bring up the

    Send Test Push window:

    For Device Token, enter the token you located above. For Message, enter a message to display in the push notification. Click Send Notification. Monitor the recipient's device (or emulator) to verify that the push

    notification arrives.

    # Upgrading from Google Cloud Messaging (GCM) to Firebase Cloud Messaging (FCM) Google has deprecated Google Cloud Messaging (GCM) in favor of Firebase Cloud

    Messaging (FCM). GCM APIs will soon be removed. Refer to Google's Firebase migration guide

    for information about migrating your app from GCM to FCM.

    NOTE If you previously had a GCM integration, we suggest upgrading your existing

    GCM project to Firebase. This will allow you to:

    Keep your Sender ID Keep your existing push integration in Iterable Update your Iterable push integration with a new Firebase server key

    With this approach, old GCM tokens remain valid and the migration will

    be almost transparent.

    # Customizing Android push notifications The following sections describe the technical setup necessary for various

    Android push notification customizations in Iterable. For marketer-specific information about how to configure these features in

    Iterable when sending a campaign, read Creating a Push Notification Campaign.

    # Adding sounds to Android push notifications To add sound to Android push notifications sent with Iterable, follow these

    instructions:

    Place the necessary sound files in the Android project's res/raw folder.

    IMPORTANT

    Sound file names should be lowercase and should not have any special

    characters. Take a look at Android's documentation about supported media formats. This documentation is not

    specific about which formats work for push notifications, so it's best to

    test as necessary.

    When setting up an Iterable push notification template, put the name of the

    sound file in the Sound field.

    NOTES

    To use the default push notification sound, set this field to default. Whether or not a device plays the sound or vibrates depends on the

    user's device settings.

    # Adding deep links to Android push notifications Iterable push notification templates make it possible to set deep link

    URLs for iOS and Android. To learn more about using Iterable's Android SDK to handle deep links,

    take a look at the Iterable Android SDK documentation

    on GitHub. If your app is not using Iterable's Android SDK, it can still handle a deep

    link contained in an Iterable push notification. Iterable provides the deep

    link URL in the defaultAction object included in the notification's

    payload. When this object's type field is set to openUrl, the data

    field will contain the deep link URL. After a user has opened a tapped on a push notification to open the app,

    use the getPayloadData() method on IterableApi to access the notification

    payload.

    # Setting the background color of a push notification To set the background color of a push notification, update the

    AndroidManifest.xml file: <meta-data android:name="iterable_notification_color" android:value="#FFFFFF"></meta-data>

    #FFFFFF can be replaced with any hex color. In stock Android, the

    notification icon and action buttons will be tinted with this color. Alternatively, you can also use a color resource: <meta-data android:name="iterable_notification_color" android:resource="@color/notification_color"/>

    # Add custom icons to your push notifications By default, push notifications display the application icon. To use a

    different icon, place the image resource inside your app's res/drawable

    directory. Then, edit AndroidManifest.xml, adding the following line: <meta-data android:name="iterable_notification_icon" android:resource="@drawable/ic_notification_icon"/>

    In this case, ic_notification_icon is the name of the notification icon. Alternatively, call setNotificationIcon(String iconName) to use the custom

    icon, referencing the image asset by name and without a file extension.

    # Further reading For more information about push notifications in Iterable, read:

    Push Notification Setup FAQ. Creating a Push Notification Campaign

    View Article
  • This document describes how to implement an image carousel in an iOS

    push notification sent by Iterable. Apple Rich Push Notifications

    IMPORTANT Carousels are not an officially support feature of Iterable push

    notifications.

    # Table of contents

    Add a Notification Content Extension to your Xcode targets

    Add code to the AppDelegate

    Add pre-written code to your app

    Adding images

    Test a push

    Further reading

    # Add a Notification Content Extension to your Xcode targets Go to File > New > Target and create a Notification Extension: This will create some new files in Xcode.

    # Add code to the AppDelegate Add some code to the bottom of your AppDelegate file to reference the new

    Content Extension. //In didFinishLaunchingWithOptions

    NotificationHelper.registerNotification()

    UNUserNotificationCenter.current().delegate = self

    //Below main Class in extension

    extension AppDelegate : UNUserNotificationCenterDelegate {

    @available(iOS 10.0, *)

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

    completionHandler();

    }

    }

    # Add pre-written code to your app You can then add the files from this GitHub repository:

    https://github.com/BFMarks/CarouselPush. When using Iterable to send the push notification that has a carousel, set

    the iOS Category to the UNNotificationExtension value from the

    Info.plist file. In the examples below, the value is

    myNotificationCategory:

    Info.plist value:

    iOS Category in Iterable:

    # Adding images At the time of this writing, the Iterable UI does not support multiple

    images. Work around this limitation by adding the parameters as one string

    with comma-separated values in the payload dictionary. {

    "title": "Title 1,Title 3,Title 3",

    "deep_link": "://deeplink1,://deeplink2,://deeplink3",

    "images": "https://iterable.com/wp-content/uploads/2016/12/Iterable_Logo_transparent-tight.png,https://dudodiprj2sv7.cloudfront.net/product-logos/dX/qp/NIJXVXZVD189-180x180.PNG,https://dudodiprj2sv7.cloudfront.net/product-logos/dX/qp/NIJXVXZVD189-180x180.PNG"

    }

    The Notification Content Extension code will parse out these values.

    # Test a push Send a test push to make sure the carousel works as anticipated.

    # Further reading For more information about push notifications in Iterable, read:

    View Article
  • # Within Iterables In-App Template Editor, you can create in-app animations

    using simple CSS! There are a variety of ways of presenting the in-app and in

    this example, we will use an elliptic pop-up.

    # Table of contents

    Creating the template

    Adding animations

    Full code example

    # Creating the template In order to use custom CSS inside of an Iterable in-app, you must create a

    template via the WYSIWYG editor. If you are very uncomfortable with HTML,

    then you can build your in-app in the Bee Free editor and export it to HTML

    for upload.

    # Adding animations You will need to add two parts of code to the template in order to achieve

    the animations.

    The keyframe reference: @keyframes slide-in-elliptic-bottom-fwd {

    0% {

    -webkit-transform: translateY(600px) rotateX(30deg) scale(0);

    transform: translateY(600px) rotateX(30deg) scale(0);

    -webkit-transform-origin: 50% 100%;

    transform-origin: 50% 100%;

    opacity: 0;

    }

    100% {

    -webkit-transform: translateY(0) rotateX(0) scale(1);

    transform: translateY(0) rotateX(0) scale(1);

    -webkit-transform-origin: 50% -200px;

    transform-origin: 50% -200px;

    opacity: 1;

    }

    }

    The animation code: .modal-content {

    background-color: #ffffff;

    margin: auto;

    border: 0;

    width: 85%;

    border-radius: 8px;

    max-width: 320px;

    position: relative;

    animation: slide-in-elliptic-bottom-fwd 1.0s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;

    animation-iteration-count: 1;

    animation-delay: 0.5s;

    }

    Full code example If you are having trouble getting your in-app to animate, try adding the

    pop-up below, customizing it as necessary: <!DOCTYPE html>

    <html lang="en">

    <head>

    <title></title>

    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"><!-- <link href="style.css" rel="stylesheet" type="text/css" /> -->

    <style type="text/css">body {

    font-family: Arial, sans-serif;

    }

    h1{

    color:#232323;

    }

    h2{

    color:#232323;

    }

    p{

    color: #4a4a4a;

    margin-top:-12px;

    }

    .modal {

    display: yes;

    position: fixed;

    z-index: 1;

    padding-top: 10%;

    left: 0;

    top: 0;

    width: 100%;

    height: 100%;

    overflow: auto;

    background-color: rgb(0,0,0);

    background-color: rgba(0,0,0, 0.7);

    }

    /* ----------------------------------------------

    * Generated by Animista on 2019-6-19 17:23:47

    * w: http://animista.net, t: @cssanimista

    * ---------------------------------------------- */

    /**

    * ----------------------------------------

    * animation slide-in-elliptic-bottom-fwd

    * ----------------------------------------

    */

    @keyframes slide-in-elliptic-bottom-fwd {

    0% {

    -webkit-transform: translateY(600px) rotateX(30deg) scale(0);

    transform: translateY(600px) rotateX(30deg) scale(0);

    -webkit-transform-origin: 50% 100%;

    transform-origin: 50% 100%;

    opacity: 0;

    }

    100% {

    -webkit-transform: translateY(0) rotateX(0) scale(1);

    transform: translateY(0) rotateX(0) scale(1);

    -webkit-transform-origin: 50% -200px;

    transform-origin: 50% -200px;

    opacity: 1;

    }

    }

    /* Modal Content */

    .modal-content {

    background-color: #ffffff;

    margin: auto;

    border: 0;

    width: 85%;

    border-radius: 8px;

    max-width: 320px;

    position: relative;

    animation: slide-in-elliptic-bottom-fwd 1.0s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;

    animation-iteration-count: 1;

    animation-delay: 0.5s;

    }

    .image-container {

    position: relative;

    width: 100%;

    border-top-left-radius: 8px;

    border-top-right-radius: 8px;

    }

    /* The Close Button */

    .image-container .close {

    color: #9f9f9f;

    position: absolute;

    right: 12px;

    top: 12px;

    font-size: 40px;

    font-weight: light;

    background-color: transparent;

    border:none;

    text-decoration:none;

    }

    .contenttext{

    padding-left:7.5%;

    padding-right:7.5%;

    padding-top: 0px;

    text-align: center;

    }

    .cta{

    width:100%;

    text-align: center;

    padding-top: 8px;

    padding-bottom: 24px;

    }

    .cta .btn{

    height:40px;

    background-color: #ed8623;

    border:0;

    border-radius: 40px;

    text-align: center;

    min-width: 120px;

    color: #ffffff;

    font-size: 0.875em;

    font-family: Arial, sans-serif;

    }

    .outside{

    margin-top: 24px;

    font-size:.875em;

    text-align: center

    }

    .outside .dismiss{

    color: #ffffff;

    background-color: transparent;

    border:none;

    }

    </style>

    </head>

    <body>

    <div class="modal" id="myModal"><!-- Modal content -->

    <div class="modal-content">

    <div class="image-container">

    <br />

    <br />

     

    <div style="text-align:center"><img alt="BGimage" style="max-width:180px;" width="240" src="https://iterable.com/wp-content/uploads/2016/12/Iterable_Logo_transparent-tight.png" />

    </div>

    <a class="close" href="itbl://"></a>

    </div>

    <div class="btn">

    <div class="contenttext">

    <h1><span style="color:#003e7d;">INTRODUCING

    <br />

    ANIMATIONS</span>

    </h1>

    <p>{{firstName}}, tracking your in-app

    <br />

    is as easy as adding this code.

    </p>

    </div>

    <div class="cta">

    <button class="btn">Try It Now!

    </button>

    <br />

     

    </div>

    </div>

    </div>

    </div>

    </body>

    </html>

    View Article
  • Within Iterable's in-app message template editor, you can create in-app

    carousels. #

    # Table of contents

    Creating the template

    Adding a carousel

    # Creating the template In order to use custom CSS inside of an Iterable in-app, you must create a

    template via the WYSIWYG editor. If you are very uncomfortable with HTML,

    then you can build your in-app in the Bee Free editor and export it to HTML

    for upload.

    Notes You must use full screen view to render this in-app carousel.

    Adding a carousel Example code: <!DOCTYPE html>

    <html lang="en">

    <head>

    <title></title>

    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">

    <style type="text/css">body {

    font-family: Arial, sans-serif;

    }

    h1{

    color:#232323;

    }

    h2 {

    color:#232323;

    }

    p {

    color: #4a4a4a;

    margin-top:-12px;

    }

    /* The Modal (background) */

    .modal {

    display: yes;

    /* Hidden by default */

    position: fixed;

    /* Stay in place */

    z-index: 1;

    /* Sit on top */

    /* padding-top: 10%;

    padding-bottom: 10%;*/

    /* Location of the box */

    left: 0;

    top: 0;

    width: 100%;

    /* Full width */

    height: 100%;

    /* Full height */

    overflow: auto;

    /* Enable scroll if needed */

    background-color: rgb(0,0,0);

    /* Fallback color */

    background-color: rgba(0,0,0,0.7);

    /* Black w/ opacity */

    }

    /* Modal Content */

    .modal-content {

    background-color: #ffffff;

    border: 0;

    width: 85%;

    border-radius: 8px;

    max-width: 320px;

    /*max-height: calc(100% - 1em);*/

    max-height: 90vh;

    margin: 0 auto;

    position: relative;

    animation-duration: 1.5s;

    animation-name: slide-up;

    animation-iteration-count: 1

    }

    @media screen and (orientation:portrait) {

    .modal-content {

    top: 25%;

    }

    @keyframes slide-up {

    from {

    top: 100%

    }

    to {

    top: 25%

    }

    }

    }

    @media screen and (orientation:landscape) {

    .modal-content {

    top: 5vh;

    }

    @keyframes slide-up {

    from {

    top: 100%

    }

    to {

    top: 5vh;

    }

    }

    }

    .image-container {

    position: relative;

    width: 100%;

    border-top-left-radius: 8px;

    border-top-right-radius: 8px;

    }

    /* The Close Button */

    .image-container .close {

    color: #9f9f9f;

    position: absolute;

    right: 12px;

    top: 12px;

    font-size: 40px;

    font-weight: light;

    background-color: transparent;

    border:none;

    text-decoration:none;

    }

    .contenttext{

    padding-left:7.5%;

    padding-right:7.5%;

    padding-top: 0px;

    text-align: center;

    }

    .cta{

    width:100%;

    text-align: center;

    padding-top: 8px;

    padding-bottom: 24px;

    }

    .cta .btn{

    height:40px;

    background-color: #ed8623;

    border:0;

    border-radius: 40px;

    text-align: center;

    min-width: 120px;

    color: #ffffff;

    font-size: 0.875em;

    font-family: Arial, sans-serif;

    }

    .outside{

    margin-top: 24px;

    font-size:.875em;

    text-align: center

    }

    .outside .dismiss{

    color: #ffffff;

    background-color: transparent;

    border:none;

    }

    .carousel {

    position: relative;

    width:200px;

    border:10px solid white;

    margin:20px auto 40px auto;

    box-shadow:0px 0px 40px #000;

    }

    .carousel > img {

    display:none;

    width:100%;

    }

    .carousel > input {

    position:absolute;

    left:-9999px;

    }

    .carousel > input:checked + label + img {

    display:block;

    }

    .carousel > label,

    .carousel > input:checked ~ label ~ label ~ label ~ label {

    display:none;

    }

    .carousel > input:checked + label {

    display:block;

    left:0;

    }

    .carousel > input:checked ~ label ~ label ~ label {

    display:block;

    right:0;

    }

    .carousel > label {

    position:absolute;

    top:0;

    width:25%;

    height:100%;

    visibility:hidden;

    }

    .carousel > label:before {

    content:'';

    display:block;

    position:absolute;

    width:100%;

    height:100%;

    visibility:visible;

    }

    .carousel > label:after {

    display:block;

    position:absolute;

    top:50%;

    width:25px;

    height:25px;

    line-height:22px;

    margin:-15px 10px 0 10px;

    background-color:black;

    color:white;

    font-family:'Arial';

    font-weight:bold;

    font-size:18px;

    text-align:center;

    visibility:hidden;

    border:2px solid white;

    border-radius:20px;

    box-shadow:0 3px 4px black;

    }

    .carousel > label:after {

    visibility:visible;

    }

    .carousel > input:checked + label:after {

    left:0;

    content:'\00AB';

    }

    .carousel > input:checked ~ label ~ label ~ label:after {

    right:0;

    content:'\00BB';

    }

    </style>

    </head>

    <body>

    <div id="myModal" class="modal"><!-- Modal content -->

    <div class="modal-content" style="padding-bottom: 10px;">

    <div class="image-container">

    <br />

     

    <div style="text-align:center"><img alt="BGimage" style="max-width:180px;" width="172" src="https://static.iterable.com/f2111070fa144bf9b92868933306b744/19-08-08-iterable-logo-navy (1).png" />

    </div>

    <a class="close" href="itbl://"></a>

    </div>

    <div class="btn">

    <div class="contenttext">

    <h1><span style="color:#00185c;">The latest styles!</span>

    </h1>

    </div>

    </div>

    <div class="carousel">

    <input id="image1" type="radio" checked="checked" name="image-selector" /> <label for="image4">View image 4</label> <img alt="" width="200" height="133" src="https://www.dropbox.com/s/6pzu0i8xe5vnuiw/mens-watch-and-ring_925x.jpg?dl=1" />

    <input id="image2" type="radio" name="image-selector" /> <label for="image1">View image 1</label> <img alt="" width="200" height="133" src="https://www.dropbox.com/s/6hidqmdjngze1gg/man-using-smartphone_925x.jpg?dl=1" />

    <input id="image3" type="radio" name="image-selector" /> <label for="image2">View image 2</label> <img alt="" width="200" src="https://www.dropbox.com/s/sh74vw612sqi3o9/mens-leather-dress-shoes_925x.jpg?dl=1" />

    <input id="image4" type="radio" name="image-selector" /> <label for="image3">View image 3</label> <img alt="" width="200" height="133" src="https://www.dropbox.com/s/i3hqrqude82vxqd/white-faced-watch_925x.jpg?dl=1" /> <label for="image4">View image 4</label> <label for="image1">View image 1</label>

    </div>

    </div>

    </div>

    </body>

    </html>

    View Article
  • #

    # Table of contents

    Overview

    How an app receives in-app messages Example in-app workflow

    Custom payload

    # Overview In-app messages are custom messages that appear while a mobile app is in

    the foreground. Unlike push notifications, they do not appear when the app is

    in the background or closed. In-app messages can:

    Be created with raw HTML or a drag-and-drop editor. Contain buttons for closing the message or navigating to specific content. Be sent as part of blast, triggered, or workflow-based campaigns. Be displayed in any order, or prevented from displaying at all. Contain metadata that the associated mobile app can inspect. Point to new content or functionality in your app, promotions, and other

    important information.

    # How an app receives in-app messages Iterable in-app works by sending a silent push

    to your app to notify the client side that there is an in-app message in the

    queue, ready for our user to view.

    # Example in-app workflow

    A marketer sets up an Iterable in-app or Mobile Inbox in the Iterable

    dashboard. The Iterable system sends a silent push notification to the mobile app. The mobile app receives the silent push and pulls down (does a GET

    request) the most recent in-app messages. Remote messages on the server are added to the local storage for increase

    performance and speed. The user is presented the in-app(s) messages with little workload on

    client-side performance.

    Custom payload A custom payload enbales developers to include:

    Prioritization around which in-app messages to show first Determine which view should present the in-app message Apply additional personalization with Handlebars

    View Article
  • #

    # Table of contents

    Default behavior

    Overriding whether to show or skip a particular in-app message

    Getting the local queue of in-app messages

    Handling in-app message buttons and links

    Changing the display interval between in-app messages

    # Default behavior By default, when an in-app message arrives from the server, the SDK

    automatically shows it if the app is in the foreground. If an in-app message

    is already showing when the new message arrives, the new message will be

    shown 30 seconds after the currently displayed in-app message closes

    ( see how to change this default value below ).

    Once an in-app message is shown, it will be "consumed" from the server queue

    and removed from the local queue as well. There is no need to write any code

    to get this default behavior.

    # Overriding whether to show or skip a particular in-app message An incoming in-app message triggers a call to the onNewInApp method of

    IterableConfig.inAppHandler (an IterableInAppHandler object). To override

    the default behavior, set inAppHandler in IterableConfig to a custom

    class that overrides the onNewInApp method. onNewInApp should return

    InAppResponse.SHOW to show the incoming in-app message or

    InAppResponse.SKIP to skip showing it. class MyInAppHandler implements IterableInAppHandler {

    @Override

    public InAppResponse onNewInApp(IterableInAppMessage message) {

    if (/* add conditions here */) {

    return InAppResponse.SHOW;

    } else {

    return InAppResponse.SKIP;

    }

    }

    }

    // ...

    IterableConfig config = new IterableConfig.Builder()

    .setPushIntegrationName("myPushIntegration")

    .setInAppHandler(new MyInAppHandler())

    .build();

    IterableApi.initialize(context, "<your-api-key>", config);

    # Getting the local queue of in-app messages The SDK keeps the local in-app message queue in sync by checking the server

    queue every time the app goes into foreground, and via silent push messages

    that arrive from Iterable servers to notify the app whenever a new in-app

    message is added to the queue. To access the in-app message queue, call

    IterableApi.getInstance().getInAppManager().getMessages(). To show a

    message, call IterableApi.getInstance().getInAppManager().showMessage(message). // Get the in-app messages list

    IterableInAppManager inAppManager = IterableApi.getInstance().getInAppManager();

    List<IterableInAppMessage> messages = inAppManager.getMessages();

    // Show an in-app message

    inAppManager.showMessage(message);

    // Show an in-app message without consuming (not removing it from the queue)

    inAppManager.showMessage(message, false)

    # Handling in-app message buttons and links The SDK handles in-app message buttons and links as follows:

    If the URL of the button or link uses the action:// URL scheme, the SDK

    passes the action to IterableConfig.customActionHandler.handleIterableCustomAction(). If

    customActionHandler (an IterableCustomActionHandler object) has not been

    set, the action will not be handled. For the time being, the SDK will treat itbl:// URLs the same way as

    action:// URLs. However, this behavior will eventually be deprecated

    (timeline TBD), so it's best to migrate to the action:// URL scheme

    as it's possible to do so.

    The iterable:// URL scheme is reserved for action names predefined by

    the SDK. If the URL of the button or link uses an iterable:// URL known

    to the SDK, it will be handled automatically and will not be passed to the

    custom action handler. The SDK does not yet recognize any iterable:// actions, but may

    do so in the future.

    The SDK passes all other URLs to IterableConfig.urlHandler.handleIterableURL().

    If urlHandler (an IterableUrlHandler object) has not been set, or if it

    returns false for the provided URL, the URL will be opened by the system

    (using a web browser or other application, as applicable).

    Changing the display interval between in-app messages To customize the time delay between successive in-app messages, set

    inAppDisplayInterval on IterableConfig to an appropriate value in

    seconds. The default value is 30 seconds.

    View Article
  • #

    # Table of contents

    In-app messages

    Default behavior

    Overriding whether to show or skip a particular in-app message

    Getting the local queue of in-app messages

    Handling in-app message buttons and links

    Changing the display interval between in-app messages

    # In-app messages In-app messages are handled via silent push messages from the server. When

    your application receives a silent push, call the Iterable iOS SDK in your

    app delegate, as follows: Swift // In AppDelegate.swift

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    IterableAppIntegration.application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler)

    }

    Objective-C - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

    [IterableAppIntegration application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];

    }

    # Default behavior By default, when an in-app message arrives from the server, the SDK

    automatically shows it if the app is in the foreground. If an in-app message

    is already showing when the new message arrives, the new in-app message will

    be shown 30 seconds after the currently displayed in-app message closes (see

    how to change this default value ).

    Once an in-app message is shown, it will be "consumed" from the server queue

    and removed from the local queue as well. There is no need to write any code

    to get this default behavior.

    # Overriding whether to show or skip a particular in-app message An incoming in-app message triggers a call to the onNew method of

    IterableConfig.inAppDelegate (an object of type IterableInAppDelegate).

    To override the default behavior, set IterableConfig.inAppDelegate to a

    custom class that overrides the onNew method. onNew should return .show

    to show the incoming in-app message or .skip to skip showing it. Swift class YourCustomInAppDelegate : IterableInAppDelegate {

    func onNew(message: IterableInAppMessage) -> InAppShowResponse {

    // perform custom processing

    // ...

    return .show // or .skip

    }

    }

    Objective-C // Implement this method in your custom class that implements IterableInAppDelegate

    // This will most likely be the global AppDelegate class.

    - (enum InAppShowResponse)onNewMessage:(IterableInAppMessage * _Nonnull)message {

    // perform custom processing

    // ...

    return InAppShowResponseShow; // or InAppShowResponseSkip

    }

    // ...

    // Now set this custom class in IterableConfig

    IterableConfig *config = [[IterableConfig alloc] init];

    config.inAppDelegate = self; // or other class implementing the protocol

    [IterableAPI initializeWithApiKey:@"YOUR API KEY" launchOptions:launchOptions config:config];

    # Getting the local queue of in-app messages Until they are consumed by the app, all in-app messages that arrive from the

    server are stored in a local queue. To access this local queue, use the

    read-only IterableAPI.inAppManager property (an object which conforms to

    the InAppManager protocol). By default, all in-app messages in the local

    queue will be consumed and removed from this queue. To keep in-app messages

    around after they are shown, override the default behavior (as described

    above). Swift // Get the in-app messages list

    let messages = IterableAPI.inAppManager.getMessages()

    if messages.count == 0 {

    print("Don't present 0")

    } else {

    print("presents the first message")

    IterableAPI.inAppManager.show(message: messages[0])

    }

    // How to override the consume:

    // Show an in-app message without consuming, i.e., not removing it from the queue

    IterableAPI.inAppManager.show(message: message, consume: false)

    Objective-C // Get the in-app messages list

    NSArray *messages = [IterableAPI.inAppManager getMessages];

    // Show an in-app message

    [IterableAPI.inAppManager showMessage:message];

    // Show an in-app message without consuming, i.e., not removing it from the queue

    [IterableAPI.inAppManager showMessage:message consume:NO callbackBlock:nil];

    # Handling in-app message buttons and links The SDK handles in-app message buttons and links as follows:

    If the URL of the button or link uses the action:// URL scheme, the SDK

    passes the action to IterableConfig.customActionDelegate.handle(). If

    customActionDelegate (an IterableCustomActionDelegate object) has not

    been set, the action will not be handled. For the time being, the SDK will treat itbl:// URLs the same way as

    action:// URLs. However, this behavior will eventually be deprecated

    (timeline TBD), so it's best to migrate to the action:// URL scheme

    as it's possible to do so.

    The iterable:// URL scheme is reserved for action names predefined by

    the SDK. If the URL of the button or link uses an iterable:// URL known

    to the SDK, it will be handled automatically and will not be passed to the

    custom action handler. The SDK does not yet recognize any iterable:// actions, but may

    do so in the future.

    The SDK passes all other URLs to IterableConfig.urlDelegate.handle(). If

    urlDelegate (an IterableUrlDelegate object) has not been set, or if it

    returns false for the provided URL, the URL will be opened by the system

    (using a web browser or other application, as applicable).

    Take a look at this sample code

    for a demonstration of how to implement and use the IterableURLDelegate and

    IterableCustomActionDelegate protocols. The following code demonstrates how to assign a urlDelegate and

    customActionDelegate to an IterableConfig object: Swift let config = IterableConfig()

    config.urlDelegate = YourCustomUrlDelegate()

    config.customActionDelegate = YourCustomActionDelegate()

    Changing the display interval between in-app messages To customize the time delay between successive in-app messages (default value

    of 30 seconds), set inAppDisplayInterval to an appropriate value (in

    seconds). Swift let config = IterableConfig()

    // ten second delay between in-app presentations

    config.inAppDisplayInterval = 10.0

    View Article
  • This document lists comprehensive sets of Iterable track events for

    several verticals. Each vertical listed below contains carefully selected

    track events that we recommend recording. #

    # Table of contents

    E-commerce

    Travel

    Gaming

    Entertainment & Streaming

    Fintech - P2P lending

    # E-commerce

    NOTES If you are using Shopify, please check out our Shopify Integration.

    Signup Login Add_to_cart Abondan_cart Add_to_wishlist Initiated_checkout Purchase Share Churn Subscription

    # Travel

    NOTES Iterable maintains all you events in perpituity which is ideal for travel

    apps.

    Signup Login Started_booking Abondan_booking Purchase Share Churn Subscription

    # Gaming

    NOTES Gaming apps include games such as arcade, strategy, educational games and

    even gambling. The events that we recommend recording in gaming apps are

    in-app purchases, sharing on social media and inviting friends.

    Login Signup Purchase Level_achieved Tutorial_completion Share Invite Bonus_claimed

    # Entertainment & Streaming

    NOTES Iterable events are as close to real-time as possible, so you can rely on

    time sensitive event triggers.

    Login Signup Start_trial Purchase Media_play Share Invite Media_save

    Fintech - P2P lending

    NOTES Please do not include any personal identifiable financial information within

    your Iterable events.

    Registration_submitted Signup Fill_Loan_form Submit_loan_application Loan_accepted Loan_rejected Payment Payment_completed

    View Article
  • Iterable Custom Conversion Tracking The Iterable SDK provides easy code to track user events enabling your team

    to record a specific action at a given time. Iterable will also collect user

    track calls from your website, mobile-app, tablet or offline events to ensure

    all of your events aggregate back to the same user across multiple devices.

    # Table of contents

    Event tracking specifications

    Attribution definition

    Attribution methodologies

    # Event tracking specifications Before you start adding Iterable event tracking SDK code to your app, you will

    want to spec-out which events to track. At a high level, you will want to

    think about each of the milestones within your user journey (sign up, viewed

    product, add to cart, purchase, share). Your Iterable Implementation Manager

    can assist on this section but we also have some recommended events in the

    following sections.

    NOTES It is not recommended to add a session event or app launch event to your

    app because it happens far more frequently than other events. This creates a

    noise and can distract from the main signal coming from your data.

    # Attribution definition Campaign Attribution is the idea of attributing (or giving credit) a

    particular conversion event (or user action) to a given campaign. For example, if you are testing different content in three push notification

    campaigns, you will want to track and attribute your conversion event to

    ensure your team knows which push notification is most effective for your

    given user base. Some common custom conversion events could be:

    Started_Trial, Shared_Item_With_Friend, Added_Item_to_Cart.

    # Attribution methodologies Iterable uses two common methodologies for attributing events back to

    particular campaigns. By default, the majority of the mobile attribution

    tracking will be automatically handled by the SDK. Here are the two options for attribution when creating a campaign within

    Iterable:

    Campaign ID explicitly set Only conversion events with a campaignId field set to this campaign will

    be attributed to the campaign.

    Attribution window When the Attribution Window is chosen, all Custom Conversions Events in

    the given time frame will be automatically attributed to the that

    particular campaign.

    Read more about

    View Article
  • This document describes various API endpoints that can be used to manage

    users and devices in Iterable, without using the mobile SDK.

    # Table of contents

    Creating and updating users User profile update

    Managing devices

    Register device token

    Disable device

    # Creating and updating users Users can be created and updated in Iterable with the API when a user logs

    into the mobile app, updates their profile, or uses a feature within the app.

    Anonymous users can also be created in Iterable via a userId if an email

    address is not known yet.

    # User profile update To add a user or update a user profile, ake a POST call to

    /users/update.

    This call will add new fields and update existing fields as necessary.

    Data is merged; fields missing from the call to the API are not deleted

    from the user profile. To identify the user, you must pass either email or

    userId. If you provide both, email takes precedence. Sample request body: {

    "email": "[email protected]",

    "dataFields": {

    "catName": "Jimmy"

    },

    "userId": "1",

    "mergeNestedObjects": true

    }

    Optional fields in this sample request include: email, userId,

    mergeNestedObjects

    # Creating a user without an email address To create a user profile for a user that does not have a known email

    address, make a POST call to /users/update.

    In the request body, set preferUserId to true and supply a value for

    userId.

    # mergeNestedObjects When calling the /users/update

    API endpoint, if mergeNestedObjects is set to true, then Iterable will

    merge top-level object data (as opposed to single fields), instead of

    overwriting it. mergeNestedObjects defaults to false. For example, if a user profile has data such as: { "mySettings": { "mobile": true } }

    And the API request contains the following data: { "mySettings": { "email": true } }

    With mergedNestedObjects set to true, the resulting merged profile

    would be: { "mySettings": { "mobile": true, "email": true } }

    With mergeNestedObjects set to false, the resulting merged profile

    would be: { "mySettings": { "email": true } }

    # Managing devices Devices can be registered and disabled by calling Iterable's API with the

    platform, token, and applicationName for the messaging service set up

    in Iterable. By default, endpointEnabled will be set to true on a

    user profile when the devie token/regID is successfully added. /users/disableDevice

    # Register device token To register a mobile device token, which enables push notifications, make a

    POST call to /users/registerDeviceToken.

    To identify the user, you must pass either email or userId. If you provide

    both, email takes precedence.

    NOTE To learn more about push notifications, read

    Push notification setup (iOS and Android).

    Sample request body: {

    "email": "[email protected]",

    "device": {

    "token": "sampleToken123",

    "platform": "APNS",

    "applicationName": "Pizza Tracker",

    "dataFields": {

    "phoneType": "iPhone 6 plus"

    }

    },

    "userId": "2"

    }

    Optional fields in this sample request include: email, dataFields, and

    userId. If a user disables push notifications for the app after the device has been

    added, it is up to the app developer to call the /users/disableDevice

    API endpoint to mark that device's endpointEnabled property to false in

    Iterable. Otherwise, if that user is included in future push sends, they will

    still be included in the send number, although they will not receive the

    message. It is important to regularly disable devices for users who have

    opted out of push in order to have accurate campaign metrics.

    # Disable device To disable a device, and prevent it from receiving further push notifications,

    make a POST call to . You must include the device token when making

    this call. If the token exists on multiple user profiles, including email will

    disable the token for that one email address only. If email is not

    included, the token will be disabled from all user profiles. The same is

    true for including or omitting userId. Sample request body: {

    "token": "sampleToken123",

    "email": "[email protected]",

    "userId": "2"

    }

    Optional fields in this sample request include: email, userId

    View Article
  • To engage users on mobile devices, Iterable's API can be used for things such

    as event tracking, purchase tracking, and the sending of messages. It is not

    necessary to use Iterable's mobile SDKs to call these endpoints. This document describes various mobile-related API endpoints.

    # Table of contents

    Custom event tracking POST /api/events/track

    Push notifications POST /api/events/trackPushOpen

    In-app messages

    POST /api/events/trackInAppOpen

    POST /api/events/trackInAppClick

    Tracking Purchases POST /api/commerce/trackPurchase

    # Custom event tracking Actions taken by users within a mobile app can be sent to Iterable using the

    POST /api/events/track endpoint.

    # POST /api/events/track Use this to send custom events, such as user logins, signups and app opens to

    Iterable. These events can then be used to trigger

    workflows

    or for custom conversion tracking

    in campaigns. Data fields in custom event calls can be used to populate merge

    parameters in templates. You can also segment on these events in the user

    profile. If createdAt field is not included, event will be sent

    immediately. Either email or userId must be passed in to identify the user.

    If both are passed in, email takes precedence. An optional string id parameter may be passed as one of the top-level

    parameters. If an event exists with that id, the event will be updated. If no

    id is specified, a new id will automatically be generated and returned.

    NOTE An id value must:

    Contain only alphanumeric characters and hyphens. Be no longer than 512 bytes in length. Be unique across all custom events in the project.

    Sample JSON request body: {

    "email": "[email protected]",

    "eventName": "startedMembership",

    "id": "12345",

    "dataFields": {

    "source": "facebook",

    "membershipType": "monthly"

    },

    "userId": "1",

    "campaignId": 123,

    "templateId": 123

    }

    Optional fields: email, id, dataFields, userId, campaignId, and

    templateId.

    # Push notifications

    # POST /api/events/trackPushOpen When a push notification is sent to a device, either by publishing a push

    campaign or adding a push action to a workflow, Iterable will automatically

    track successful sends under the push campaign metrics. When the push notification is opened on the device, the app will need to call

    the POST /api/events/trackPushOpen

    endpoint. Either email or userId must be passed in to identify the user.

    If both are passed in, email takes precedence. Include the campaignId in

    the call, and Iterable will attribute the open to the campaign that sent the

    notification. Read Sending Push Notifications

    to learn more. Sample JSON request body: {

    "email": "[email protected]",

    "userId": "2",

    "campaignId": 12345,

    "templateId": 67890,

    "messageId": "01234567890",

    "dataFields": {

    "openedMostRecentPush": true

    }

    }

    Optional fields: email, userId, campaignId, templateId, messageId,

    dataFields

    # In-app messages Iterable can track in-app engagement from the app from through the

    POST /api/events/trackInAppOpen

    endpoint and the POST /api/events/trackInAppClick

    endpoints. To learn more about receiving, rendering, and tracking in-app

    messages, read Setting up in-app messages (without the SDK).

    # POST /api/events/trackInAppOpen Use this endpoint to track an in-app notification opens. Either

    email or userId must be passed in to identify the user. If both are

    passed in, email takes precedence. To learn more, read

    In-app message overview. Sample JSON request body: {

    "email": "[email protected]",

    "userId": "123",

    "messageId": "01234567890"

    }

    Optional fields: email, userId

    # POST /api/events/trackInAppClick Use this endpoint to track an in-app notification clicks. Either email or

    userId must be passed in to identify the user. If both are passed in,

    email takes precedence. To learn more, read

    In-app message overview. {

    "email": "[email protected]",

    "userId": "123",

    "messageId": "01234567890"

    }

    Optional fields: email, userId

    # Tracking Purchases

    # POST /api/commerce/trackPurchase Track in-app purchases by calling Iterable's POST /api/commerce/trackPurchase

    endpoint. Tracking purchases allows marketers to segment based on purchase history,

    trigger workflows, and attribute revenue to campaigns. When a purchase event for a user is tracked, it will also clear the

    shoppingCartItems on the user's profile. Adding in the campaignId will

    attribute the purchase to specific Iterable campaign.

    NOTE We recommend casting the required price and total fields as doubles

    instead of longs. To do that, you will need to include a number with a

    decimal in the first call that you use to cast that field. Use a non-zero

    decimal value to cast the field as a double (example: 5.55). Otherwise, the

    field will be cast as a long.

    An optional string id parameter may be passed as one of the top-level

    parameters. If a purchase event exists with that id, the event will be

    updated. If no id is specified, a new id will will automatically be

    generated and returned.

    NOTE An id value must:

    Contain only alphanumeric characters and hyphens. Be no longer than 512 bytes in length. Be unique across all purchase events in the project.

    Sample JSON request body: {

    "user": {

    "email": "[email protected]",

    "dataFields": {

    "totalPurchases": 5

    },

    "userId": "1"

    },

    "items": [

    {

    "id": "1",

    "sku": "1",

    "name": "Iterable Stickers",

    "description": "Put these stickers anywhere and everywhere!",

    "categories": [

    "stickers",

    "novelty"

    ],

    "price": 5.50,

    "quantity": 2,

    "imageUrl": "http://static.iterable.com/iterable-demo-v1/15-03-04-Iterable_stickers.jpg",

    "url": "iterable.com"

    }

    ],

    "campaignId": 14348,

    "templateId": 29592,

    "total": 11,

    "dataFields": {

    "shippingAddress1": "360 3rd Street",

    "shippingAddress2": "Suite 675",

    "city": "San Francisco",

    "state": "CA",

    "zip": 94107

    }

    }

    Required fields: user, items, items.id, items.name, items.price,

    items.quantity, total

    View Article
  • While Iterable's iOS and

    Android SDKs simplify the

    process of working with in-app messages, Iterable's API makes it possible to

    manually check for, render, and consume in-app messagesand to track events

    such as inAppClick, inAppOpen, and inAppConsume. This document

    describes API endpoints relevant to these tasks.

    NOTE When rendering in-app messages without the SDK, pay attention to scaling,

    positioning, scrolling, etc.

    # Table of contents

    Overview

    API calls

    Get in-app messages for a user

    Consume an in-app message

    Track an in-app open

    Track an in-app click

    # Overview When in-app campaigns are published or a contact in Iterable enters a

    Send in app action in a workflow, the in-app message is

    delivered to an in-app message queue for the contact (these messages are

    automatically removed after 24 hours). To display the in-app message, poll

    the message queue and display and consume in-app messages as necessary. After

    displaying a message, the mobile app should track an inAppOpen event. If a

    user clicks on a message's call to action, the app should track an

    inAppClick event. The diagram below displays how these calls work together to send, display,

    and track in-app messages through Iterable's API. /events/trackInAppClick

    NOTE To learn more about in-app messages, read the

    In-app messages overview.

    # API calls

    # Get in-app messages for a user To fetch in-app messages for a specific user, make a GET request to the

    /inApp/getMessages

    API endpoint. Sample request URL: https://api.iterable.com:443/api/inApp/getMessages?email=chris%40iterable.com&userId=1234&count=123&api_key=[API_KEY]

    # Consume an in-app message To consume an in-app message, make a POST request to the

    /events/inAppConsume

    API endpoint. Sample request body: {

    "email": "[email protected]",

    "userId": "123",

    "messageId": "01234567890"

    }

    To identify the user, you must pass either email or user. If you provide

    both, email takes precedence.

    # Track an in-app open To track when a user opens an in-app message, make a POST request to the

    /events/trackInAppOpen

    API endpoint. Sample request body: {

    "email": "[email protected]",

    "userId": "123",

    "messageId": "01234567890"

    }

    To identify the user, you must pass either email or user. If you provide

    both, email takes precedence.

    # Track an in-app click To track when a user clicks on an in-app message, make a POST request to the

    API endpoint. Sample request body: {

    "email": "[email protected]",

    "userId": "123",

    "messageId": "01234567890"

    }

    To identify the user, you must pass either email or user. If you provide

    both, email takes precedence.

    View Article
  • While Iterable's SDK contains all of the functionality out of the box to

    set up deep links, some teams might choose to avoid including additional SDKs

    in their apps. To take full advantage of Iterable's deep linking without the

    SDK, add the following code snippetwhich automatically handles the click

    track and redirect within the app.

    # iOS #define ITBL_DEEPLINK_IDENTIFIER @"/a/[a-zA-Z0-9]+"

    - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler {

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:ITBL_DEEPLINK_IDENTIFIER options:0 error:NULL];

    NSString *urlString = userActivity.webpageURL.absoluteString;

    NSTextCheckingResult *match = [regex firstMatchInString:urlString options:0 range:NSMakeRange(0, [urlString length])];

    void (^customRouteCallback)(NSString *) = ^(NSString * routeURL) {

    //<MAKE A CUSTOM CALL TO YOUR APP'S ROUTES HERE WITH THE 'routeURL'>

    };

    if (match == NULL) {

    customRouteCallback(urlString);

    } else {

    NSURLSessionDataTask *trackAndRedirectTask =

    [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:urlString]

    completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

    customRouteCallback(response.URL.absoluteString);

    }];

    [trackAndRedirectTask resume];

    }

    return YES;

    }

    View Article
  • In this section we will discuss migrating from another push provider over to

    Iterable. #

    # Table of contents

    Migrating push notifications to iterable

    1. Install the Iterable SDK

    2. Configure your app to support push notifications from Iterable

    Transfering tokens

    Migrating channel preferences

    Slow migration Selectively targeting users

    # Migrating push notifications to iterable To migrate to Iterable you will need to simply have your app developers

    install the Iterable SDK and add historical user device token to over to

    Iterable's system.

    # 1. Install the Iterable SDK You can find documentation for iOS here

    and Android here.

    NOTES

    Integrating Iterable push notifications will not cause any issues with

    other push notification services in your app. All push notifications are handled by Apple and Google frameworks and

    multiple providers can be in the same app at the same time.

    # 2. Configure your app to support push notifications from Iterable You can find push notification documentation for iOS here

    and Android here. Then all new data will start to flow into iterable. The operating system will

    maintain whether you have valid permissions from the user to engage in that

    channel. If the user has not given permissions on push notifications, then

    Iterable will mark them as unsubscribed from mobile push.

    # Transfering tokens You can transfer all of your user device tokens from your previous provider

    to Iterable. This is accomplished with the /registerDeviceToken API. Loop through all active tokens and add it to the /registerDeviceToken

    Iterable API. If this is a new user, you will also need to call

    /users/update in order to set any user fields.

    NOTES Transfering tokens is not mandatory as you can simply wait till your users

    update the app to include the Iterable SDK.

    # Migrating channel preferences Your users may have push channel preferences from your historical push

    provider and ypu may want to move those preferences over to Iterable! To do

    so, you will want to use the /bulkUpdateSubscriptions API to migrate over

    historical preferences.

    # Slow migration Another very common approach is to slowly migrate off of the other provider.

    This is accomplished by updating your app with the Iterable SDK and slowly

    transition your campaigns over to Iterable. You will be able to see which

    users have updated to the newest version of your app within the

    Iterable Segmentation tool.

    Selectively targeting users Within Iterable you can also selectively target your users based on their app

    versions and only send pushes to users with the Iterable SDK. Once a

    sufficient number of your users have updated, you can remove the competitor's

    SDK.

    View Article
  • When you use Android App Links in your messages, users can tap a link to your

    website and get seamlessly redirected to your installed app without going

    through a browser, all while having the links tracked within Iterable. Deep Link FAQs

    WARNING You must set up iOS deep linking

    before implementing Android deep linking (they rely on similar architecture).

    # Table of contents

    Setup

    1. Enable App Links

    2. Upload assetlinks.json

    3. Determine which links to rewrite

    4. Set up the track and get redirect call

    FAQ

    # Setup

    # 1. Enable App Links

    Set up your application to enable App Links via the instructions

    here. Create Intent Handlers for URIs Generate the assetlinks.json file

    # 2. Upload assetlinks.json

    After you generate the assetlinks.json file with your app's

    fingerprint, the .well-known/assetlinks.json file will need to be

    hosted by Iterable, so you can send it to us by email. Once the assetlinks.json file has been uploaded, you can test it out via the

    Statement List Generator and Tester.

    # 3. Determine which links to rewrite Iterable re-writes links defined by your uploaded

    apple-app-site-association file. See iOS Universal Links Setup

    to learn how to set up that file.

    # 4. Set up the track and get redirect call For App Links to work with link rewriting in emails, you need to set up an

    assetlinks.json file in the Iterable project. If you already have a urlHandler, you can use the same handler can be used

    for email deep links by calling handleAppLink in the activity that handles

    all app links in your app: // MainActivity.java

    @Override

    public void onCreate() {

    super.onCreate();

    ...

    handleIntent(getIntent());

    }

    @Override

    public void onNewIntent(Intent intent) {

    super.onNewIntent(intent);

    if (intent != null) {

    handleIntent(intent);

    }

    }

    private void handleIntent(Intent intent) {

    if (Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() != null) {

    IterableApi.handleAppLink(intent.getDataString());

    // Overwrite the intent to make sure we don't open the deep link

    // again when the user opens our app later from the task manager

    setIntent(new Intent(Intent.ACTION_MAIN));

    }

    }

    Alternatively, call getAndTrackDeeplink along with a callback to handle the

    original deep link URL. You can use this method for any incoming URLs, as it

    will execute the callback without changing the URL for non-Iterable URLs. IterableApi.getAndTrackDeeplink(uri, new IterableHelper.IterableActionHandler() {

    @Override

    public void execute(String result) {

    Log.d("HandleDeeplink", "Redirected to: "+ result);

    // Handle the original deep link URL here

    }

    });

    # FAQ For answers to common questions about deep links, read the .

    View Article
  • Below you can find how to confirm whether your events are working or how to

    fix a setup that doesn't seem to work.

    # Table of contents

    Testing

    Troubleshooting

    Push opens are not tracked

    Custom events tracking

    # Testing Navigate to Audience > Contact Lookup to view a user's tracked events: # Sample events: Click on the Event History section of your test user to confirm that your

    events are being tracked to the correct user. When inspecting the events,

    verify that the dataFields object contains any passed-in data.

    NOTES

    By default, Iterable will track some information on the user (like image or

    IP address) from third party systems. If you would like this tracking turned

    off, please notify your customer success manager or contact

    [email protected]. Custom events are starred. System events are represented with a checkbox.

    # Troubleshooting

    Double-check the API key Check the correct user based on whether you initiated the SDK with an Email

    or UserId identify call.

    # Push opens are not tracked Make sure you are on the latest version of SDK. Iterable Android SDK can be

    found here and iOS can be

    found here.

    Custom events tracking Make sure you are using a call to track event when trying to track custom

    events. You can either use API events/track or use following code to add

    custom event tracking to your app Swift IterableAPI.track(event: "Custom_event", dataFields: ["key": "value"])

    Java IterableApi.getInstance().track("Custom_event", datafields);

    View Article
  • The Iterable mobile SDK can track user events as a way to record a specific

    action at a given time.

    NOTES Iterable does not currently charge for track calls but we still encourage our

    customers to only track relevant and actionable events within the platform in

    order to reduce noise and focus on important milestones for your user.

    # Table of contents

    Custom event names

    Tracking custom events

    Tracking purchase events

    Tracking purchase event metadata

    # Custom event names It is better not to include spaces in your custom event names, because it

    requires extra handlebar logic within the plaform. For example, when a user

    signs up, you will likely want to define it as signUp or signs_up but not

    Signs Up.

    # Tracking custom events Most events tracked within Iterable will be unique to your business and

    distinct use case. Below are some examples of how to structure your custom

    events. Swift IterableAPI.track(event: "Custom_event", dataFields: ["key": "value"])

    Java IterableApi.getInstance().track("Custom_event", datafields);

    # Tracking purchase events Iterable has a dedicated endpoint for tracking purchases. It is recommended

    to use this call to enable Iterable to better track purchase analytics and

    attribution. There are 2 ways to track purchases in the Iterable SDK.

    NOTES The SDK by default will track campaign ID and Template ID. For more

    information on setting up attribution from email, please visit our deep

    linking section.

    Swift // Example price field

    let price_from_app: NSNumber = 4.99

    //Create an array of commerce Items

    let items_from_app = [CommerceItem(id: "String", name: "String", price: 4.99, quantity: 1)]

    // Iterable Track Call

    IterableAPI.track(purchase: price_from_app, items: items_from_app)

    Java Double total = new Double(4.99);

    List<CommerceItem> items = new ArrayList<CommerceItem>();

    items.add(new CommerceItem("String", "String", 4.99, 1));

    IterableApi.getInstance().trackPurchase(total, items);

    # Tracking purchase event metadata You can include datafields (also known as metadata) in the track purchase

    call as well. This can be any data that you would like to leverage in future

    campaigns. Swift // Example data fields

    let dataField : [String: Any] = [

    "Store_Address":[

    "Street1": "123 Main St",

    "Street2": "Apt 1",

    "City": "Iter-a-ville",

    "State": "Ca",

    "Zip": "90210"

    ]

    ]

    // Example price field

    let price_from_app: NSNumber = 4.99

    //Create an array of commerce Items

    let items_from_app = [CommerceItem(id: "String", name: "String", price: 4.99, quantity: 1)]

    // Iterable Track Call

    trackPurchase(price_from_app, items: items_from_app, dataFields: dataField)

    Java JSONObject store_address = new JSONObject();

    final JSONObject datafields = new JSONObject();

    try {

    store_address.put("Street1", "123 Main St");

    store_address.put("Street2", "Apt 1");

    store_address.put("City", "Iter-a-ville");

    store_address.put("State", "CA");

    store_address.put("Zip", "90210");

    datafields.put("dataFields", address);

    } catch (JSONException e) {

    e.printStackTrace();

    }

    Double total = new Double(4.99);

    List<CommerceItem> items = new ArrayList<CommerceItem>();

    items.add(new CommerceItem("String", "String", 4.99, 1));

    IterableApi.getInstance().trackPurchase(total, items, datafields);

    View Article
  • #

    # Table of contents

    Push notification setup FAQs

    What does OS Notifications toggle do?

    What is the difference between endpointEnabled and notificationsEnabled?

    When using Segment, is it possible to use the Segment Identify call to add device tokens to user profiles?

    Is it possible to send push notifications to apps that do not incorporate Iterable's mobile SDKs?

    Is it possible to export push tokens for my users from our existing push provider and add them into Iterable using the POST /users/registerDeviceToken API?

    Will users of old app versions (in which Iterable's SDK is installed) receive Iterable push notifications, assuming they have valid push tokens on their Iterable user profiles?

    If users upgrade from old app versions (without Iterable's SDK installed) to new app versions (with Iterable's SDK installed), will they receive push notifications from Iterable before opening the new version of the app?

    If users opted in to push notifications when using older versions of an app, will they continue to receive push notifications after installing new versions of that same app (even if they aren't asked to opt in to push notifications again)?

    Is it possible to track custom events and properties?

    Is there a maximum length or size for push notifications?

    What is the payload that is received on device?

    In-app message FAQs

    What kind of devices can display in-app messages?

    Are in-app messages available for all types of campaigns?

    Can in-app messages be associated with Iterable message channels?

    Is it possible to receive in-app messages in apps not configured to use push notifications?

    How can in-app messages be customized?

    When can mobile apps display in-app messages?

    How is it possible to control in-app message rendering?

    How does a mobile app know when new in-app messages are available?

    Will users see the same in-app messages more than once?

    What versions of Iterable's mobile SDK support in-app messages?

    Is it possible to receive and display in-app messages without using Iterable's mobile SDKs?

    Is it possible to create a close button that looks like an X?

    What happens when a user receives multiple in-app messages?

    What is the difference between POST /api/events/inAppConsume and POST /api/inApp/cancel?

    Deep Link FAQs

    What happens if a user clicks on a Universal Link associated with an app they do not have installed?

    Is it possible to have more than one apple-app-site-association file for my domain?

    Will this work for subdomains (cats.example.com) or only the top level domain (example.com)?

    What should an apple-app-site-association file look like? How does all this work?

    Can you illustrate the flow in a more graphical form?

    Is it possible to use wildcards in an apple-app-site-association file?

    Must the apple-app-site-association file include the Iterable appId section?

    What does an apple-app-site-association file look like?

    # Push notification setup FAQs

    # What does OS Notifications toggle do? OS Notifications toggle on Android, when enabled, let's OS render the

    notification message by sending a push of type "notification message". If you

    are using SDK, you don't need to enable the toggle. OS notifications when

    disabled send data message to Android. SDKs render data message type.

    # What is the difference between endpointEnabled and notificationsEnabled?

    endpointEnabled is a flag set on the server based on token validity.

    notificationsEnabled is a flag indicating device settings.

    # When using Segment, is it possible to use the Segment Identify call to add device tokens to user profiles? Unfortunately, you cannot use this method. You must call the Iterable

    POST /api/users/registerDeviceToken

    API endpoint to add push tokens.

    # Is it possible to send push notifications to apps that do not incorporate Iterable's mobile SDKs? Yes, this is possible. Add valid device tokens to user profiles via the

    POST /api/users/registerDeviceToken

    API endpoint. We still recommend implementing the Iterable SDK ( iOS,

    Android ) since it does

    make it easier to send the token to Iterable for new versions of your app.

    Additional benefits include automatic tracking of push opens, simple

    implementation of rich content in push notifications, and support for deep

    linking.

    # Is it possible to export push tokens for my users from our existing push provider and add them into Iterable using the POST /users/registerDeviceToken API? Yes, these push tokens should work. On Android, a push token is associated with the device, app, and the

    project/API key you request it for. On iOS, the push token is associated with the device, app, and

    certificate/provisioning profile the app is running under when requesting the

    token.

    # Will users of old app versions (in which Iterable's SDK is installed) receive Iterable push notifications, assuming they have valid push tokens on their Iterable user profiles? As long as the push token is still valid and the user has opted in to push

    notifications, the push notification will work.

    # If users upgrade from old app versions (without Iterable's SDK installed) to new app versions (with Iterable's SDK installed), will they receive push notifications from Iterable before opening the new version of the app? Depends. If APNS/GCM decides the push token remains the same with the new

    app, then it should work fine. However, the push tokens are subject to

    change. Various factors such as OS upgrades, app upgrades, wiping your

    device, etc. may or may not change the token (depending on OS and other

    factors). This Stack Overflow post

    provides more details.

    # If users opted in to push notifications when using older versions of an app, will they continue to receive push notifications after installing new versions of that same app (even if they aren't asked to opt in to push notifications again)? This will work. Each time the app is opened, the

    POST /api/users/registerDeviceToken

    API call will pass the token to Iterable. If the token has changed, it will

    update the user's profile in Iterable with the new token. Since the user has

    already opted in to receive push from your app in the past, the user will

    receive push notifications.

    # Is it possible to track custom events and properties? You can track custom events via the track function call on the track SDK. You

    can also update user contact fields via the updateUser function call on the

    SDK.

    # Is there a maximum length or size for push notifications? There are best practices for the size of your push notifications to ensure

    deliverability and high engagement rates. Here are some key numbers to keep in mind:

    Limit the size of a push notification to 2KB, including the entire

    message and its payload. 48 lines or 140280 characters: Depending on what language your team

    is using, you might be able to deliver a 2000 character message. However,

    remember that your message may be truncated after four to eight lines. Short

    and sweet is best. Plus, since we know they are on mobile, some users may be

    using expensive cellular data to engage with you instead of WiFi, so be kind

    and shrink those message sizes.

    # What is the payload that is received on device?

    The payload received on device contains a specific iterable section with

    the key itbl, which is used by the SDK to track the notification. The notification also contains all of the platform-specific information as

    expected (for example, aps for iOS).

    The custom payload data is set on the root level of the notification payload.

    iOS example: {

    "itbl": {

    "templateId": 7,

    "campaignId": 2,

    "messageId": "38e834ad76a149eb918a9d66e8dd9015",

    "isGhostPush": false

    },

    "aps": {

    "alert": "test push message"

    },

    "custom": "",

    "fields": "",

    "here": ""

    }

    Android example: Bundle[{itbl={"campaignId":207256,"isGhostPush":false,"messageId":"d3a8a725bdc34f2699272b38de3a08e0","templateId":296434}, google.sent_time=1481139004, body=Android URI deeplink test, from=668868396390, custom-key=custom-value, uri=itblTest://testingDeeplink, google.message_id=0:1512675342843879%694c27b9f9fd7ece}]

    # In-app message FAQs

    # What kind of devices can display in-app messages? iOS and Android devices can display in-app messages.

    # Are in-app messages available for all types of campaigns? Yes. Iterable supports in-app messages for blast, triggered, and

    workflow-related campaigns.

    # Can in-app messages be associated with Iterable message channels? Yes, in-app messages can be tied to different

    message channels and types.

    # Is it possible to receive in-app messages in apps not configured to use push notifications? Iterable uses silent push to notify device that in-app messages are

    available. We use silent pushes so client doesnt have to continuously poll

    the server to check if in-apps are available. If you do not have push set up,

    you will still be able to receive in-app messages on app launch and when app

    is in foreground.

    # How can in-app messages be customized? Customization of the in-app can be done from in-app templates. SDK fetches

    the HTML from server and displays.

    # When can mobile apps display in-app messages? In-app messages display when an app is in the foreground. In addition to listening for silent push notifications, Iterable's mobile SDK

    checks for new in-app messages at strategic timessuch as when the app comes

    to the foreground.

    # How is it possible to control in-app message rendering? You can call getMessages and render in-app at a specific location in your

    app.

    # How does a mobile app know when new in-app messages are available? Iterable alerts mobile apps to the existence of new in-app messages by

    sending silent push notifications. After receiving a silent push notification

    and downloading its associated in-app messages, an app can decide whether or

    not to display them, and in what order. Silent push notifications aren't visible or audible to the user. Instead,

    they're background notifications that serve as a communication mechanism

    between Iterable and the app.

    # Will users see the same in-app messages more than once? No, in-app messages will not be shown to users who have already seen them.

    # What versions of Iterable's mobile SDK support in-app messages? In-app messages have been supported since version 4.4.0

    of the iOS SDK and version 2.2.0

    of the Android SDK. However, it's always best to use the most recent version of Iterable's mobile

    SDKs. For information about the deprecation and end-of-life schedule for older

    SDK versions, read the iOS SDK Deprecation and End-of-Life Schedule

    and the Android SDK Deprecation and End-of-Life Schedule.

    # Is it possible to receive and display in-app messages without using Iterable's mobile SDKs? Yes. For instructions, read Setting up In-App Messages (Without the SDK).

    However, Iterable strongly recommends using the mobile SDKs.

    # Is it possible to create a close button that looks like an X? One way to create an X-style close button is to use the Bee Free editor with

    a configuration similar to the following:

    Add a button to the message template Set the button's text to X

    Set the button's URL to action://, which will close the in-app

    message when tapped Choose a Background Color for the button Choose a Text Color for the button For Align, choose right Specify a Border Radius of 20

    For Content Padding, specify:

    0 for Top and Bottom

    10 for Left and Right

    Specify a Solid, 1-pixel border of any desired color.

    # What happens when a user receives multiple in-app messages? Unless the mobile app has been customized to selectively display in-app

    messages, it will show all in-app messages in the order that you send them.

    # What is the difference between POST /api/events/inAppConsume and POST /api/inApp/cancel?

    POST /api/events/inAppConsume Indicates that a user has viewed or deleted an in-app message and remove

    the message from the server's message queue. It's only necessary to call

    this endpoint if you're not using one of Iterable's mobile SDKs.

    POST /api/campaigns/cancel Indicates that an in-app message should not be delivered to a user and

    remove it from the server's queue.

    # Deep Link FAQs

    # What happens if a user clicks on a Universal Link associated with an app they do not have installed? The user will get directed to your website in his/her browser, like a normal

    link, as long as your website has been set up to handle Universal Links. On iOS, this works for users running iOS 9 or higher. This also works for Android App Links.

    # Is it possible to have more than one apple-app-site-association file for my domain? Each domain can only have a single apple-app-site-association file.

    # Will this work for subdomains (cats.example.com) or only the top level domain (example.com)? We now rewrite URLs for subdomains as well as top-level domains.

    # What should an apple-app-site-association file look like? How does all this work? Here's a sample apple-app-site-association file that we will use to walk

    through the entire process: {

    "applinks": {

    "apps": [],

    "details": [

    {

    "appID": "appID.bundleID",

    "paths": [

    "/a/*" <-- [RULE 1] Mandatory rule required in all Iterable association files

    ]

    },

    {

    "appID": "iterable",

    "paths": [

    "NOT /samplepath/toignore", <-- [RULE 2] Tells Iterable to write as regular (non-Universal) link

    "/samplepath/*" <-- [RULE 3] Tells Iterable to rewrite into Universal Path

    ]

    }

    ]

    }

    }

    WARNING Only edit the fields displayed in red above.

    When you send that file to Iterable, we store a copy of it on our servers.

    When you send a message, the following happens:

    Iterable goes through each link in the message and compares it to the list

    of rules in the apple-app-site-association file to see if there is a

    match. For this example, let's assume that one of your links is

    yourdomain.com/samplepath/hello.html. If there is a match, Iterable will rewrite the link before sending it out

    in your message. In this example, yourdomain.com/samplepath/hello.html

    matches RULE 3 above and will be rewritten into

    yourdomain.com/a/ABCD1234, where ABCD1234 is a unique identifier for that

    link (you don't have to worry about this unique identifier). At this point, Iterable also stores a mapping of /a/ABCD1234 to

    /samplepath/hello.html on the Iterable servers. When a user clicks on the rewritten link /a/ABCD1234, the user's device

    will detect it based on RULE 1 in the apple-app-site-association file (a

    copy of the file is stored on device) and opens your app based on the appID

    in the file. Your app then uses the Iterable SDK to make a call to Iterable's servers

    to track the click and get the actual destination /samplepath/hello.html. Your app receives /samplepath/hello.html from the Iterable server and

    opens the destination within your app.

    # Can you illustrate the flow in a more graphical form? Sure thing! Here's a similar example for iOS Universal Links to the

    snapface.com domain.

    # Is it possible to use wildcards in an apple-app-site-association file? Yes, you can use * to specify an entire section (matches all substrings) or ?

    to match any single character. You can combine both wildcards in a single

    path, such as /foo/*/bar/201?/mypage which would match

    /foo/abc/bar/2015/mypage and /foo/def/bar/2019/mypage. For more details, check out Apple's documentation here.

    # Must the apple-app-site-association file include the Iterable appId section? Yes. The purpose of the Iterable appID section is to provide more control

    over which paths get rewritten by Iterable. If you want a subset of paths to

    be opened in Iterable but not the others, then placing those paths under the

    Iterable appID section will limit rewriting to those paths. If you want all paths to be rewritten, use: {

    "appID": "iterable",

    "paths": ["*"]

    }

    What does an apple-app-site-association file look like? Use this template to get started: {

    "applinks": {

    "apps": [],

    "details": [

    {

    "appID": "appID.bundleID",

    "paths": [

    "/a/*"

    ]

    },

    {

    "appID": "iterable",

    "paths": [

    "PATHS TO BE REDIRECTED GO HERE"

    ]

    }

    ]

    }

    }

    View Article
  • this guide

    # Table of contents

    Troubleshooting

    iOS in-app message is not shown

    Android in-app message is not shown

    No messages received

    # Troubleshooting By default, when an in-app message is sent, it sits on server queue. It gets

    pulled by SDK when App is in the foreground. You can see which in-app

    messages are in the queue by sending a test campaign and then by going to our

    API docs for In-app_getMessages,

    add your API key and email of your test user. The GET request will then return all the messages in the queue and you can

    determine if you sent the message to the right location.

    # iOS in-app message is not shown Make sure you call IterableAppIntegration from didReceiveRemoteNotification: // In AppDelegate.swift

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    IterableAppIntegration.application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler)

    }

    # Android in-app message is not shown If you are implementing your own onMessageReceived() and onNewToken()

    methods, make sure you forward onMessageReceived() and onNewToken() calls

    to IterableFirebaseMessagingService.handleMessageReceived and

    IterableFirebaseMessagingService.handleTokenRefresh respectively. @Override

    public void onMessageReceived(RemoteMessage remoteMessage) {

    IterableFirebaseMessagingService.handleMessageReceived(this, remoteMessage);

    }

    # No messages received If you do not see messages received during troubleshooting, verify your

    notification setup. Iterable uses silent push to alert the app when in-app

    is available. Follow

    to see if you have push notifications set up correctly. In iOS, make sure you have Background Fetch enabled for your app:

    View Article
  • This document describes how to set up and test the Iterable SDK. You can add

    the SDK via Cocoapods,

    Carthage, or direct import of the libraries. They

    should all have the same result.

    NOTES The Iterable iOS SDK is a Swift implementation of an iOS client for Iterable,

    for iOS versions 9.0 and higher.

    # Table Of Contents

    Table Of Contents

    CocoaPods

    Carthage

    Installing manually

    Initializing

    1. Import the IterableSDK module

    2. Create mobile API Key

    3. Set the API and initialize the SDK

    4. Add code to your app delegate

    5. Create a test user

    Next steps

    # CocoaPods To use CocoaPods to install Iterable's iOS SDK, first

    install CocoaPods. sudo gem install cocoapods

    Then, follow these steps:

    If your project does not yet have a Podfile, create one.

    In the terminal, navigate to the directory containing your project's

    .xcodeproj file

    Run the following command: pod init

    Edit your project's Podfile.

    Add the Iterable-iOS-SDK pod to your project's app target. If your app will receive push notifications containing media

    attachments (images, etc.), add the YOUR-APP-notification-extension

    pod to your project's Notification Service Extension target.

    Identifying the User After these changes, your Podfile should look similar to the

    following: platform :ios, '11.0'

    use_frameworks!

    target 'swift-sample-app' do

    pod 'Iterable-iOS-SDK'

    end

    target 'swift-sample-app-notification-extension' do

    pod 'Iterable-iOS-AppExtensions'

    end

    You must include use_frameworks! in your Podfile, no matter if

    your app is based on Swift or Objective-C. If your project cannot use

    this option, install the SDK manually.

    In the terminal, run the following command to install the SDK (and app

    extensions, if necessary): pod install

    This will create an .xcworkspace file. To open your project in Xcode,

    use this file instead of the .xcodeproj file.

    For more information, take a look at the CocoaPods

    documentation.

    # Carthage To use Carthage to install Iterable's iOS SDK, first install Carthage.

    Then, follow these steps:

    If it does not yet exist, create a file named Cartfile in the same

    directory as your Xcode project.

    Edit Cartfile, adding the following line: github "Iterable/swift-sdk"

    In the terminal, in the same directory as your Cartfile, run the

    following command: carthage update

    In Xcode, navigate to the Build Phases section for your app's target.

    Click the + icon and select New Run Script Phase. A Run Script

    section will appear.

    In the Run Script section, below the Shell input, add the

    following command: /usr/local/bin/carthage copy-frameworks

    In the Input Files section, click + and add the following path: $(SRCROOT)/Carthage/Build/iOS/IterableSDK.framework

    In the Output Files section, add the path to the copied framework: $(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/IterableSDK.framework

    Add <Xcode project directory>/Carthage/Build/iOS/IterableSDK.framework

    to your Xcode project by dragging it into the Xcode Project Navigator.

    When prompted by Xcode, add the framework to your app's target. If your app will be using push notifications that contain media

    attachments (images, etc.), repeat steps 6 through 8, substituting

    IterableAppExtensions.framework for IterableSDK.framework. In step 8,

    add IterableAppExtensions.framework to your project's Notification

    Service Extension target (instead of the app target).

    For more information, take a look at the Carthage

    documentation.

    # Installing manually Attached to the release, you will find two framework bundles:

    IterableSDK.framework and IterableAppExtensions.framework.

    In Xcode, choose the target for your app. Now, add the

    IterableSDK.framework to the Embedded Binaries section. If you want

    to use an Iterable Rich Notification Extension, you will have to add

    IterableAppExtensions.framework to the embedded binaries section as well.

    If you want to use an Iterable Rich Notifiation Extension, you will need

    to add IterableAppExtension.framework to Linked Frameworks and

    Libraries section of your app extension target (not app target). Please

    note that you will have to add the IterableAppExtension.framework bundle

    to both the app target (step 1) and app extension target (step 2) of your

    project. In the app target, it goes in the Embedded Binaries section and

    in app extension target it goes in the Linked Frameworks and Libraries

    section.

    In build settings, set Always Embed Swift Standard Libraries setting

    to Yes. This is necessary for both Swift and Objective-C projects.

    # Initializing Now that the SDK library is referencable by the app, it must be initialized:

    Import the IterableSDK module Set the API and Configuring the SDK Initialize

    # 1. Import the IterableSDK module To use the IterableSDK module, import it at the top of your Objective-C

    or Swift files: Swift // In AppDelegate.swift file

    // and any other file where you are using IterableSDK

    import IterableSDK

    Objective-C // In AppDelegate.m file

    // and any other file where you are using IterableSDK

    @import IterableSDK;

    NOTES If you have errors please see our troubleshooting at the end of this section

    # 2. Create mobile API Key Go to Integrations > API Keys and create a mobile specific API for your

    app, as shown below: Screenshot of selection choice.

    # 3. Set the API and initialize the SDK In the application:didFinishLaunchingWithOptions: method of your app

    delegate, call initialize(apiKey:launchOptions:config:), passing in your

    Iterable API key: Swift let config = IterableConfig()

    config.customActionDelegate = self

    config.urlDelegate = self

    //We will add our push integration names later

    config.sandboxPushIntegrationName = "<your-bundle-app-ID>"

    config.pushIntegrationName = "<your-bundle-app-ID>"

    IterableAPI.initialize(apiKey: "<your-api-key>", launchOptions: launchOptions, config: config)

    Objective-C IterableConfig *config = [[IterableConfig alloc] init];

    config.sandboxPushIntegrationName = @"<your-bundle-app-ID>";

    config.pushIntegrationName = @"<your-bundle-app-ID>";

    [IterableAPI initializeWithApiKey:@"<your-api-key>" launchOptions:launchOptions config:config]

    NOTES Iterable config() provides configuration and customization options for the

    Iterable SDK. We will use it later for setting up push and in-app.

    # 4. Add code to your app delegate We will cover this code in more detail in each section later but for now,

    please add this code to your AppDelegate file.

    # Code for push notifications Swift func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    IterableAPI.register(token: deviceToken)

    }

    Objective-C - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

    [IterableAPI registerToken:deviceToken];

    }

    # Code for push tracking From this method, call the userNotificationCenter(_:didReceive:withCompletionHandler:)

    method on IterableAppIntegration. This tracks a push open event and

    performs the associated action. Swift public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

    IterableAppIntegration.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler)

    }

    Objective-C - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {

    [IterableAppIntegration userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];

    }

    # Code for in-app messages In-app messages are handled via silent push messages from the server. When

    your application receives a silent push, call the Iterable iOS SDK in your

    app delegate, as follows: Swift // In AppDelegate.swift

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    IterableAppIntegration.application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler)

    }

    Objective-C - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

    [IterableAppIntegration application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];

    }

    Turn on Remote Notifications under Signing and Capabilities in Your

    Xcode Target.

    # 5. Create a test user Register a test email right after the config file and you should now see a

    test user within the Contact Lookup section of the platform. Swift IterableAPI.email = "[email protected]"

    IterableAPI.updateUser(["init_test":"test"], mergeNestedObjects: false)

    Objective-C IterableAPI.email = @"[email protected]";

    Go to Iterable, select Audiences > Segmentation and click refresh to see

    your test user! If you do not see your test user, read

    Testing and Troubleshooting the Iterable SDK.

    # Next steps After the SDK has been installed, read about .

    View Article
  • Iterable's Android SDK Release Notes Iterable's iOS and Android mobile SDKs help you to:

    # Send and track push notifications

    The Iterable SDK will automatically track push notification sends, opens,

    and bounces Automatically track device uninstalls Maintain the most up-to-date device tokens

    # Send and track in-app messages

    Reduce load on your system by sending a silent push to the device to

    efficiently pull in-apps to the device Store in-apps on the device for faster load time Use a mobile inbox

    # Save implementation time

    Provide error handling to ensure accuracy Minimize the amount of code needed to deploy your mobile app with Iterable Provide tested and proven code for new Apple / Android OS updates Easily update user profile and event data

    # Automatically track and attribute engagement events

    Update user profile and event data for enriched triggered campaigns Automatically attribute to conversion events to specific campaigns Help measure effectiveness of your campaigns

    NOTES Itegrating the Iterable SDK will save your team time and effort. However,

    it is possible to connect your mobile app to Iterable without using the SDK.

    # Without the Iterable SDK Without the Iterable SDK you will lose some benefits of the platform and it

    will require significantly more effort, especially around:

    Push action buttons In-app modals Automatic tracking of attribution data Mobile Inbox

    # iOS Next Steps

    iOS SDK Initialization and Setup User Identity Tracking events iOS Push Notifications iOS Deep Linking iOS In-app Messages Mobile Inbox

    # iOS Sample projects and Github For sample projects, look at the following repositories:

    Swift sample project Objective-C sample project Swift Github Objective-C Github Iterable's iOS SDK Release Notes

    # Android Next Steps

    Android SDK Initialization and Setup User Identity Tracking events Android Push Notifications Android Deep Linking Android In-app Messages Mobile Inbox

    # Android Github

    Android Github

    View Article
  • Here are some common issues with troubleshooting your SDK initialization. Identifying the User

    # Table of contents

    iOS SDK initialization testing

    iOS SDK troubleshooting

    CocoaPods troubleshooting

    Carthage troubleshooting

    Manual import troubleshooting

    Android SDK initialization testing

    Android SDK initialization troubleshooting

    Gradle sync failed

    Multiple push providers

    Next steps

    # iOS SDK initialization testing

    Can you add the import the library without an error: import IterableSDK

    Double check your API credentials

    # iOS SDK troubleshooting

    # CocoaPods troubleshooting

    Update your pods Check the syntax of your podfile Ensure you're opening the Xcode .xcworkspace, not the .xcodeproject file

    Make sure you have uncommented use_frameworks!. You must include

    use_frameworks! in your Podfile, no matter if your app is based on Swift or

    Objective-C. If your project cannot use this option, install the SDK

    manually. If you see this error: [!] CocoaPods could not find compatible versions for pod "Iterable-iOS-AppExtensions":

    In Podfile:

    Iterable-iOS-AppExtensions

    There are only pre-release versions available satisfying the following requirements:

    'Iterable-iOS-AppExtensions', '>= 0'

    You should explicitly specify the version in order to install a pre-release version

    Make sure you are using verified latest release of

    CocoaPods. To update CocoaPods run following command in the terminal: sudo gem install cocoapods

    Make sure you add the Iterable-iOS-AppExtensions pod, without a specific

    version (or =>0).

    # Carthage troubleshooting

    Update to the latest released version of the SDK Update Carthage

    # Manual import troubleshooting

    Ensure you manually linked the libraries Check that the libraries are listed in your Linked Frameworks and Library

    section under the General tab

    # Android SDK initialization testing To make sure SDK is successfully integrated, perform a gradle sync.

    # Android SDK initialization troubleshooting

    # Gradle sync failed

    Gradle sync failed with ERROR: Failed to resolve: com.iterable:iterableapi:3.1.3

    Ensure you have jcenter() in project level gradle file:

    allprojects {

    repositories {

    google()

    jcenter()

    }

    }

    # Multiple push providers To learn how to work with multiple push providers, please read

    Setting up Android Push Notifications.

    # Next steps After installing the SDK, please read .

    View Article
  • Update User Optional Recommendations The Iterable SDK can identify users by email or user ID.

    # Table of contents

    Overview

    Identifying the user by email

    Identifying the user by user ID

    Identifying the device of the user

    Auto push registration

    Send the device token to Iterable

    Updating the user email and a customer userId

    Next steps

    # Overview To identify a user, you'll need to do two things: specify an email address

    or user ID, and then call updateUser to send that value to Iterable.

    # Identifying the user by email Email is typically used as the key identify within Iterable because it tracks

    across devices to aggregate data between a user's phones, tablet, web-site

    activity or even IoT (Internet-of-Things) device. Iterable also allows for multi-dimensional nested data types, meaning you can

    organize your data based on relevant key values. Once you have an email address or user ID for your app's current user, set

    IterableAPI.email or IterableAPI.userId. For example:

    WARNING

    Don't specify both email and userId in the same call, as they will be

    treated as different users by the SDK. Only use one type of identifier, email

    or userId, to identify the user. Your app will not be able to receive push notifications until you set one

    of these values

    Add this line of code as soon as you know the user's email: Swift IterableAPI.email = "[email protected]"

    Objective-C IterableAPI.email = @"[email protected]";

    Java IterableApi.getInstance().setEmail("[email protected]");

    NOTES Please see Iterable-Specific User Specific Profile Fields

    to ensure you don't add data that is specific to set fields in Iterable.

    # Identifying the user by user ID Iterable can also identify user by user ID. However, all things being equal,

    it is recommended to use email as the key identifier. Swift IterableAPI.userId = "user123"

    Objective-C IterableAPI.userId = @"user123";

    Java IterableApi.getInstance.setUserId("user123");

    You can add the userId identifier at any point after the IterableConfig()

    call.

    NOTES

    When creating a user with a userId, Iterable also assigns that user a

    fake email adress (using the placeholder.email domain). For example,

    setting a userId of user123 gives that user anemail similar to

    [email protected]. We will discuss in the next section

    how we can update the email of an unkown user. A user ID can be up to 52 characters long.

    # Identifying the device of the user For Iterable to send push notifications to an iOS device, it must know the

    unique token assigned to that device by Apple or Android. Iterable uses silent push notifications to tell iOS apps when to fetch new

    in-app messages from the server. Because of this, your app must register for

    remote notifications with Apple even if you do not plan to send it any push

    notifications.

    # Auto push registration IterableConfig.autoPushRegistration determines whether or not the SDK will: Automatically register for a device token when the the SDK is given a new

    email address or user ID. Disable the device token for the previous user when

    a new user logs in. If IterableConfig.autoPushRegistration is true (the default value): Setting IterableAPI.email or IterableAPI.userId causes the SDK to

    automatically call the registerForRemoteNotifications() method on

    UIApplication and pass the resulting device token to the

    application(_:didRegisterForRemoteNotificationsWithDeviceToken:) method on

    the app delegate. If IterableConfig.autoPushRegistration is false: After setting IterableAPI.email or IterableAPI.userId, you must

    manually call the registerForRemoteNotifications() method on

    UIApplication. This will fetch the device token from Apple and pass it to

    the application(_:didRegisterForRemoteNotificationsWithDeviceToken:) method

    on the app delegate.

    # Send the device token to Iterable

    NOTES

    Iterable users the device token to send push notifications and in-app

    messages. Users do not need to opt in to Apple push notifications for Iterable to get

    the device token.

    To send the device token to Iterable and save it on the current user's

    profile, call IterableAPI.register(token:) from the

    application(_:didRegisterForRemoteNotificationsWithDeviceToken:) method on

    UIApplicationDelegate. For example: Swift func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    IterableAPI.register(token: deviceToken)

    }

    Objective-C - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

    [IterableAPI registerToken:deviceToken];

    }

    Java

    // Iterable SDK automatically registers the push token with Iterable

    // whenever setEmail or setUserId is called.

    // If you want to trigger token registration manually, first disable automatic

    // registration by calling setAutoPushRegistration(false) on IterableConfig.Builder when initializing the SDK.

    // Than call registerForPush whenever you want to register the token:

    // Only use this line if you want to register push manually.

    // IterableApi.getInstance().registerForPush();

    Once you register for push, you should see the device on the user profile,

    which can be accessed by going to the Iterable dashboard, clicking

    Audiences > Contact Lookup. Now you'll always have the most up to date device token and can export Device

    Identifier (IDFA) for future marketing campaigns.

    # Updating the user email and a customer userId This code body is used to identify users when you have both the email and

    UserID. You need to add the new user ID in two places. Swift IterableAPI.updateEmail("[email protected]", onSuccess: { (_) in

    IterableAPI.updateUser([AnyHashable.ITBL_KEY_USER_ID : "new_user_id"], mergeNestedObjects: false, onSuccess: { (_) in

    IterableAPI.userId = "new_user_id" // note this needs to be set after both calls have finished successfully

    }, onFailure: { (_, _) in

    ITBError()

    })

    }) { (_, _) in

    ITBError()

    }

    Java IterableApi.getInstance().updateEmail("[email protected]", new IterableHelper.SuccessHandler() {

    @Override

    public void onSuccess(JSONObject data) {

    JSONObject userIDobj = new JSONObject();

    try {

    userIDobj.put("userId", "newUserId");

    } catch (JSONException e) {

    e.printStackTrace();

    }

    IterableApi.getInstance().updateUser(userIDobj);

    }

    }, new IterableHelper.FailureHandler() {

    @Override

    public void onFailure(String reason, JSONObject data) {

    Log.e(TAG, reason)

    }

    });

    # Next steps To troubleshoot user identification, read User Testing and Troubleshooting. If you have successfully identified the user for your use case, please read

    Updating User Profile

    and . If you are seeing your user incorrectly identified, please read

    View Article
  • Iterable can customize your push notifications with action buttons, animated

    GIFs, images, sounds, and deep linking. Setting up Android Push Notifications

    # Table of contents

    Adding a push extension

    Configure support for rich push notifications

    Adding sounds to iOS push notifications

    Adding deep links to iOS push notifications

    Further reading

    # Adding a push extension Follow these instructions:

    First, create a push extension in the target settings of Xcode. This is

    will enable your extension to reference the pre-built libraries of code. Edit your project's Podfile. Add the Iterable-iOS-SDK pod to your projec's app target. If your app will receive push notifications containing media

    attachments (images, etc.), add the Iterable-iOS-AppExtensions pod to

    your project's Notification Service Extension target.

    After these changes, your Podfile should look similar to the

    following: platform :ios, '11.0'

    use_frameworks!

    target 'swift-sample-app' do

    pod 'Iterable-iOS-SDK'

    end

    target 'swift-sample-app-notification-extension' do

    pod 'Iterable-iOS-AppExtensions'

    end

    You must include use_frameworks! in your Podfile, no matter if

    your app is based on Swift or Objective-C. If your project cannot use

    this option, install the SDK manually. The following sections describe the technical setup necessary for various

    iOS push notification customizations in Iterable. For marketer-specific information about how to configure these features in

    Iterable when sending a campaign, read

    Creating a Push Notification Campaign.

    # Configure support for rich push notifications For push notifications to contain images, animated GIFs, video, or action

    buttons, you must create a Notification Service Extension. The Iterable iOS SDK provides a Notification Service Extension implementation

    that handles media attachments and action buttons. To use it:

    Include Iterable-iOS-AppExtensions in your Podfile, as explained

    above. Create a new target of type Notification Service Extension in your

    Xcode project. If you are calling Iterable SDK from Swift, edit the NotificationService

    class (auto-generated by Xcode) so that it extends

    ITBNotificationServiceExtension. If you are using Objective-C, use delegation instead of inheritance.

    Swift import UserNotifications

    import IterableAppExtensions

    class NotificationService: ITBNotificationServiceExtension {

    }

    Objective-C // File: NotificationService.m

    #import "NotificationService.h"

    @import IterableAppExtensions;

    @interface NotificationService ()

    @property (nonatomic, strong) ITBNotificationServiceExtension *baseExtension;

    @end

    @implementation NotificationService

    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {

    self.baseExtension = [[ITBNotificationServiceExtension alloc] init];

    [self.baseExtension didReceiveNotificationRequest:request withContentHandler:contentHandler];

    }

    - (void)serviceExtensionTimeWillExpire {

    [self.baseExtension serviceExtensionTimeWillExpire];

    }

    @end

    # Adding sounds to iOS push notifications To add sound to iOS push notifications, follow these instructions:

    Place the necessary sound files in the iOS project's Library/Sound

    folder, or in the top-level directory of the Xcode project.

    NOTE See Apple's UNNotificationSound documentation

    for a list of supported sound formats.

    When creating a push notification template in Iterable, put the name of the

    sound file in the Sound field:

    NOTES

    To use the default push notification sound, set this field to default. Whether or not a device plays the sound or vibrates depends on the

    user's device settings.

    # Adding deep links to iOS push notifications Iterable push notification templates make it possible to set deep link

    URLs for iOS and Android. To learn more about using Iterable's iOS SDK to handle deep links,

    take a look at the Iterable iOS SDK documentation

    on GitHub. If your app is not using Iterable's iOS SDK, it can still handle a deep link

    contained in an Iterable push notification. Iterable provides the deep link

    URL in the defaultAction object included in the notification's payload.

    When this object's type field is set to openUrl, the data field will

    contain the deep link URL. When using the SDK, code executing after an app has opened in response to a

    user's interaction with a push notification can use

    IterableApi.lastPushPayload to access the push notification's payload.

    # Further reading For more information about push notifications in Iterable, read:

    Frequently Asked Questions Creating a Push Notification Campaign Push Notification Testing and Troubleshooting Iterable iOS SDK docs Apple's UserNotifications framework documentation

    .

    View Article
  • A deep link is a URI that links to a specific location within your mobile

    app. The following sections describe how to work with deep links using

    Iterable's iOS SDK. Android App Links Setup

    NOTES You should be able to use the same schema (pre-defined paths for presenting

    deep linking to a user) as your email or third party deep links.

    # Table of contents

    iOS deep links

    Android deep links

    Handling links from push notifications

    Handling email links

    # iOS deep links Push notifications and action buttons may have openUrl actions attached to

    them. When a URL is specified, the SDK first calls the urlDelegate object

    specified on your IterableConfig object. You can use this delegate to

    handle openUrl actions the same way as you handle normal deep links. If the

    delegate is not set or if it returns false (the default), the SDK will open

    the URL with Safari. If, upon receiving a deep link, you want to navigate to

    a specific view controller in your app, do so in the urlDelegate. In the code below, DeepLinkHandler is a custom handler which is reponsible

    for deep link navigation. You have to provide an implementation for deep link

    navigation. Please see the sample

    application

    for a reference implementation for DeeplinkHandler. Swift func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // ...

    // Initialize Iterable API

    let config = IterableConfig()

    // ...

    config.urlDelegate = self

    IterableAPI.initialize(apiKey: apiKey, launchOptions:launchOptions, config: config)

    // ...

    }

    // Iterable URL Delegate. It will be called when you receive

    // an `openUrl` event from push notification.

    func handle(iterableURL url: URL, inContext context: IterableActionContext) -> Bool {

    return DeeplinkHandler.handle(url: url)

    }

    Objective-C - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // ...

    // Initialize Iterable SDK

    IterableConfig *config = [[IterableConfig alloc] init];

    // ...

    config.urlDelegate = self;

    [IterableAPI initializeWithApiKey:@"YOUR API KEY" launchOptions:launchOptions config:config];

    // ...

    }

    - (BOOL)handleIterableURL:(NSURL *)url context:(IterableActionContext *)context {

    // Assuming you have a DeeplinkHandler class that handles all deep link URLs and navigates to the right place in the app

    return [DeeplinkHandler handleUrl:url];

    }

    # Android deep links

    # Handling links from push notifications Push notifications and action buttons may have openUrl actions attached to

    them. When a URL is specified, the SDK first calls the urlHandler specified

    in your IterableConfig object. You can use this class to handle openUrl

    actions the same way as you handle normal deep links. If the handler is not

    set or returns NO, the SDK will open a browser with that URL. // MyApplication.java

    @Override

    public void onCreate() {

    super.onCreate();

    // ...

    IterableConfig config = new IterableConfig.Builder()

    .setPushIntegrationName("myPushIntegration")

    .setUrlHandler(this)

    .build();

    IterableApi.initialize(context, "YOUR API KEY", config);

    }

    @Override

    public boolean handleIterableURL(Uri uri, IterableActionContext actionContext) {

    // Assuming you have a DeeplinkHandler class that handles all deep link URLs and navigates to the right place in the app

    return DeeplinkHandler.handle(this, uri);

    }

    # Handling email links For App Links to work with link rewriting in emails, you need to set up an

    assetlinks.json file in the Iterable project. For more information, read

    . If you already have a urlHandler, the same handler can be used for email

    deep links by calling handleAppLink in the activity that handles all app

    links in your app: // MainActivity.java

    @Override

    public void onCreate() {

    super.onCreate();

    // ...

    handleIntent(getIntent());

    }

    @Override

    public void onNewIntent(Intent intent) {

    super.onNewIntent(intent);

    if (intent != null) {

    handleIntent(intent);

    }

    }

    private void handleIntent(Intent intent) {

    if (Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() != null) {

    IterableApi.handleAppLink(intent.getDataString());

    // Overwrite the intent to make sure we don't open the deep link

    // again when the user opens our app later from the task manager

    setIntent(new Intent(Intent.ACTION_MAIN));

    }

    }

    Alternatively, call getAndTrackDeeplink along with a callback to handle the

    original deep link URL. You can use this method for any incoming URLs, as it

    will execute the callback without changing the URL for non-Iterable URLs. IterableApi.getAndTrackDeeplink(uri, new IterableHelper.IterableActionHandler() {

    @Override

    public void execute(String result) {

    Log.d("HandleDeeplink", "Redirected to: "+ result);

    // Handle the original deep link URL here

    }

    });

    View Article
  • This document describes various best practices to consider when working with

    push notifications. FCM

    # Table of contents

    Tracking uninstalls

    Migrating GCM to FCM for Android

    Renewing push certificates in Iterable

    # Tracking uninstalls Iterable will automatically track app uninstalls. The methodology is as

    follows:

    A push campaign is sent to the end user. 12 hours later a "ghost push" is sent the user (a ghost push being a

    silent push that will not alert the user). If the ghost push is failed to be delivered to the device due to the app

    being uninstalled, the app uninstall is then tracked in Iterable.

    # Migrating GCM to FCM for Android For Android push notification, Google Cloud Manager (GCM) has been deprecated

    in favor of FireBase Cloud Messages (FCM). If you are on GCM, you must

    migrate to the new system. You can migrate an existing GCM client app on

    Android to Firebase Cloud Messaging (FCM) using the instructions in this

    guide. Before getting started, keep in mind the following:

    GCM and FCM SDKs cannot co-exist within an application. GCM tokens retrieved via GoogleCloudMessaging.register() or

    InstanceID.getToken() will continue to work in FCM without any modification

    or renewal.

    Please follow this Google documentation

    to complete the migration.

    # Renewing push certificates in Iterable Your push notifications certificates are generally only valid for one year.

    Once they expire, you must renew them by creating new certificates and

    uploading them to Iterable.

    NOTES

    Apple should send you an email when your push notification certificate is

    close to expiring. It is worth adding a calendar reminder to ensure you know exactly when the

    certificates will expire. The Iterable dashboard will also note your certificates expiration date in

    the Mobile Apps section.

    Please follow the steps in the previous section around creating certificates.

    Once you have new valid certificates, you can upload them to Iterable and

    continue to receive push in your app.

    Apple Docs

    View Article

Curious about Iterable?

Anonymously Ask Iterable Any Question

Ask Anonymous Question

×
Rate your company