Content Triggers

Send Back in Stock and Price Drop notifications through Lifecycle Optimizer triggered by content updates.

Content Triggers in Lifecycle Optimizer

To send Back in Stock or Price Drop notifications, create flows in Lifecycle Optimizer which will trigger when your content is updated. These notifications can be sent to users who have subscribed to content notifications, e.g. by adding a product to their wishlist or by subscribing to back in stock notifications.

Products that your users have subscribed to are stored in the Watchlist (visible on user profiles). You can also create a flow in Lifecycle Optimizer to send a confirmation message when an item is added to a subscriber's Watchlist (using the Content Watched trigger).

The platform can automatically create watchlist entries for items left in abandoned carts. For other types of interest, you'll need to implement API endpoints to manage your users' Watchlists.

For flows entered by this entry type, the following Zephyr variables will be available for use in your template:

  • watched_content_key_type (e.g. 'url' or 'sku')
  • watched_content_key (e.g. 'https://example.com/my-content' or 'SKU-123')
  • watched_interest_type (e.g. 'back-in-stock')

You can use these values to retrieve and display the watched content or make relevant recommendations.

To get started, you will need:
  • A server-side application which can interact with APIs, either directly or with one of our API client libraries
  • One or more actions or behaviors of your site that you'd like to record as interest.
  • The type of interest that you want to record for each action. We currently support these types:
    • Notify me when this item is back in stock: back-in-stock
    • Notify me when this item is available for preorder: preorder
    • Wishlist / Favorite / Like: wishlist
    • If these do not meet your needs, reach out to your CSM to discuss your use case.

Server-side implementation for the Content Watch API

API Endpoint: content/watch

Save or retrieve watches: profiles' specific interests in individual content items. You may wish to create a watch when a user requests to be notified once an item is back in stock or available for preorder, or when they interact with an item-specific wishlist/favorite/like button. Endpoint URL: https://api.sailthru.com/content/watch
GET Mode
Given a content item, find a list of profiles that are watching it. Expired watches will not be returned.

Example Call

{
   "content_id": "https://example.com/product-1",
   "content_id_type": "url",
   "limit": 20
}

Example Response

[
   {
       "id": 67,
       "interest_type": "back-in-stock",
       "profile_id": "598a131a2ddf9c759c7e1b56",
       "query": {
           "content_id": "54f74818897e2c577727abf2"
       }
   }
]
Required Parameters
  • content_id: A content ID.
Optional Parameters
  • content_id_type: The type of the content ID provided. Can be "url" or "id". Defaults to "id".
  • limit: Maximum number of results to return. Requests may not retrieve more than 100 results.
POST Mode

Save a new watch, recording a user's interest in content.

Example Call

{
   "profile_id": "example@example.com",
   "profile_id_type": "email",
   "watch": {
       "interest_type": "back-in-stock",
       "query": {
           "content_id": "https://example.com/product-1",
           "content_id_type": "url"
       }
   }
}

Example Call (with expire date)

{
   "profile_id": "example@example.com",
   "profile_id_type": "email",
   "watch": {
       "interest_type": "added-to-cart",
       "query": {
           "content_id": "https://example.com/product-1",
           "content_id_type": "url"
       },
       "expire_date": "2029-10-12T07:20:50.52Z"
   }
}

Example Response

{
   "id": 67,
   "interest_type": "back-in-stock",
   "profile_id": "598a131a2ddf9c759c7e1b56",
   "query": {
       "content_id": "54f74818897e2c577727abf2"
   }
}
Required Parameters
  • interest_type: The type of interest that this user has in the given content. Can be any of back-in-stock, wishlist, added-to-cart, or preorder.
  • profile_id: A unique identifier for the user, either email address or system ID.
  • query: A set of criteria that define the content being watched. Currently requires you to specify content_id, with an optional content_id_type for which you can provide the value "url" if you have provided a URL as the ID.
Optional Parameters
  • profile_id_type: If the identifier is not a system ID, this should be included and specify the type of identifier provided, such as email.
  • expire_date: The date a watch should expire. The date format is expected to be in ISO 8601 format i.e 2019-10-12T07:20:50.52Z. Once this date is reached the watcher will no longer receive notifications for the subscribed watch. Defaults to no expiration date.
DELETE Mode

Permanently delete a watch.

Example Call

{
   "content_id": "https://example.com/product-1",
   "content_id_type": "url",
   "profile_id": "example@example.com",
   "profile_id_type": "email",
   "interest_type": "wishlist"
}

Example Response

Successful responses will have no content (HTTP status code 204).
Required Parameters
  • profile_id: A unique identifier for the user, either email address or system ID.
  • content_id: A URL or a system ID for the content item being watched.
  • interest_type: The type of watch to delete. Can be back-in-stock, wishlist, preorder, or to delete watches of all interest types you may use *.
Optional Parameters
  • profile_id_type: If the identifier is not a system ID, this should be included and specify the type of identifier provided, such as email.
  • content_id_type: The type of the content ID provided. Can be "url" or "id". Defaults to "id".

API Endpoint: content/watch/profile

Interact with a specific profile's watch list

GET Mode
Given a profile, get a list of content the profile is watching. You may retrieve up to 100 results, and you will receive the 100 most recent content items that match the provided values. Expired watches will not be returned.

Example Call

{
   "profile_id": "example@example.com",
   "profile_id_type": "email",
   "interest_type": "*",
   "limit": 10
}

Example Response

[
   {
       "id": 67,
       "interest_type": "back-in-stock",
       "profile_id": "598a131a2ddf9c759c7e1b56",
       "query": {
           "content_id": "54f74818897e2c577727abf2"
       }
   }
]
Required Parameters
  • interest_type: The type of watches to find. Can be back-in-stock, wishlist, preorder, or to find all watches you may use *.
  • profile_id: A unique identifier for the user, either email address or system ID.
Optional Parameters
  • profile_id_type: If the identifier is not a system ID, this should be included and specify the type of identifier provided. Currently supports only email.
  • limit: Maximum number of results to return. Requests may not retrieve more than 100 results.

Expiring watchlist items

If you want items added to your users' watchlists to expire after a certain time period, use the existing API endpoint for removing an item from watchlist.

Managing updates to a subscriber's watchlist

When a subscriber watches a content item, create a watch by using POST /content/watch. When a subscriber unwatches or purchases the item, delete the watch by using DELETE /content/watch.

Viewing a subscriber's watchlist

See GET Mode forcontent/watch/profile.  

Client-side Implementation

You can record watched content using the SPM client-side JavaScript using the watchContent integration described below.

watchContent

Adds a content item to a user's watchlist. If the requested watch already exists, no action will be taken.
Sailthru.integration('watchContent', {
   email: ,
   interest_type: 'back-in-stock', // or 'wishlist', 'preorder' query: {
       content_id: ,
       content_id_type: 'url'
   }
});
Parameters
  • email or id: Required. A unique user identifier.
  • key: When id is provided, key may also be provided to specify the type of identifier. Supported keys are 'email', 'extid', 'fb', 'sms', 'twitter'. Defaults to 'email'.
    • If you would like to provide a SID (Sailthru ID) for the profile, the key value should be provided as null.
  • interest_type: Required. The type of interest that the profile has expressed. Supported interest types are 'back-in-stock', 'wishlist', or 'preorder'.
  • query: Required. A set of properties that describe the content being watched. Currently, this supports two properties:
    • content_id: Required. A URL or a system ID for the content item being watched.
    • content_id_type: Required only if content_id is not a system content ID. It should contain the type of the content ID. Supported values are 'url' and 'id'.

Example

Sailthru.integration('watchContent', {
email: 'john@example.com',
interest_type: 'wishlist',
query: {
content_id: 'https://www.example.com/products/5-striped-shirt',
content_id_type: 'url'
}
});

Add Cart Abandoned items to the Watchlist

Customers who have already implemented the Purchase API can choose to automatically add Cart Abandoned items to the Watchlist, with the interest type added-to-cart. Once enabled, select Content and then Watchlist from the Settings menu. On the Watchlist Preferences page, you can enable or disable the Cart Abandoned setting. Items will be removed from the watchlist after 14 days.

Set Up Lifecycle Optimizer Flows

Use the Added to Wishlist or Back in Stock recipes to quickly create Lifecycle Optimiser flows using content triggers.

The Content Watched entry in Lifecycle Optimizer will initiate a flow when a user adds an item to their watchlist. To show watchlisted items in these email notifications, see "Displaying content from a user's Watchlist in email templates".



The Content Changed entry in Lifecycle Optimizer will initiate a flow when the content for an item reflects the conditions you set.

Display Watchlist Content in Email Templates

Using Zephyr, you can display items that a user has watchlisted in your email templates. For flows using the Content Watched entry type, the Zephyr variables watched_content_key_type and watched_content_key will be available for use in your template. You can use these values to retrieve and display the watched content or make relevant recommendations.

get_user_watchlist

The get_user_watchlist zephyr function allows you to display content that users have explicitly expressed interest in via the content watch API. get_user_watchlist returns a list of content items that can be interacted with similarly to content returned by the personalize function. Content will always be ordered by recency, with the most recently watchlisted content first.

list get_user_watchlist(string interest_type[, int limit])
  • interest_type is a string, and must be a valid interest type or the string "*".  If a watchlist type is passed, then the get_user_watchlist function will return all of the content the user is watching where the interest type matches the one given. If "*" is passed in (e.g. {watched_content = get_user_watchlist("*")}), then get_user_watchlist will return all content watched by the user being sent the email, regardless of the interest type.
  • limit is an optional integer parameter, and determines the maximum number of content items to return. Note that this function is not guaranteed to return this number of content items - if a user has watched 3 items and get_user_watchlist is called with limit 5, the function will still only return the three content items the user has watched.
    • If limit is omitted from the call, or if a number less than 1 is passed in, it will default to 20
    • If limit is passed, and is between 1 and 100 inclusive, the limit will be the amount passed in
    • If limit is passed and is greater than 100, it will default to 100.

Examples

Display the title of the content that is back in stock using load_content

Note: this only works if your content uses URL keys, i.e. watched_content_key_type must be 'url'.

{changed_item = load_content([watched_content_key])}

<p>The following item is now back in stock: {changed_item[0].title}</p>

Display the title of the content that is back in stock using personalize() with the custom algorithm

{changed_item = personalize({
    "custom_key_type": watched_content_key_type,
    "custom_keys": [watched_content_key]
})}

<p>The following item is now back in stock: {changed_item[0].title}</p>

Display similar items to the item that is now out of stock using personalize() with the context algorithm

{changed_item = personalize({
    "algorithm": "custom",
    "custom_key_type": watched_content_key_type,
    "custom_keys": [watched_content_key]
})}

<p>The following item is now out of stock: {changed_item[0].title}</p>

{similar_items = personalize({
    "algorithm": "context",
    "context_key_type": watched_content_key_type,
    "context_key": watched_content_key
})}

<p>Here are some similar items you might like:</p>

<ul>
{foreach similar_items as c}
    <li>{c.title}</li>
{/foreach}
</ul>

Content Triggers FAQ

I've set up my flows using the new triggers / recipes, how can I test these?
  • Test a flow using a trigger or recipe by making the flow active in production without sending an email as a step. Monitor how many users enter the flow to understand whether updates are being received as expected.
I've set up a "Content Updated" flow, but it's not working?
  • First, check that your content update has been received by the system, e.g. for inventory updates, are you seeing a change in inventory reflected in the Content Library?

Contact us

Top