Skip to main content
Mobile and app API

Pass data and drive personalization for your native mobile apps.

Updated over a week ago

API client types

Native apps

Fresh Relevance is normally used to retrieve the underlying data for personalization - for example, the list of product IDs that should be recommended to a visitor on a particular page in the app.

Progressive Web Apps

PWAs are more like websites. Fresh Relevance is normally used to retrieve the formatted HTML for the web page, so you would normally use either Client-side personalization or Server-side personalization, depending on the exact type of app:

Server-side personalization, web servers and Headless servers

These run on a server and usually communicate with some form of client application on a web browser. This might be built in a framework like React or Vue.js


Introduction to the Mobile and App API

When used on a website, Fresh Relevance captures data about shoppers’ behavior using JavaScript on every webpage. This JavaScript sends data to the Fresh Relevance server for each page which is visited. This is termed a beacon and includes a JSON structure containing the following types of data:

This is not an exhaustive list.

  • Product details page device ID (Cookie)

  • Product

    • ID

    • Name

    • Description

    • Value

  • Product list page device ID (Cookie)

  • Array of products

  • Cart Page Device ID (Cookie)

  • Array of products

  • Transaction complete page device ID (Cookie)

  • Email address

Additional custom data can be sent for both the person, for example a CRM ID, and for the product(s).

Data capture for mobile apps is very similar – the app needs to make an HTTP POST for each product/page that is viewed containing the same elements.

To personalize a web page or email, a Fresh Relevance Slot is used. This is a placeholder for that element which can be used on either a web page or an email. The content (SmartBlock) which is actually displayed by the Slot can be changed flexibly and at any time using the Fresh Relevance UI. The same approach works for mobile app personalization as well.

The mobile app can make an HTTP GET request to the Fresh Relevance server and retrieve back either JSON or HTML representing the slot. This can then be rendered into the mobile app.

The mobile APIs require an API key/token to be passed in the x-api-key header. This can be acquired from within the admin site: Expand the User menu and go to Settings > Other Integrations > Fresh Relevance Access Tokens > Create Token. For Token Type, select Mobile.


Recording data for Native apps and server-side personalization using the API

Data capture for mobile apps is very similar to server side personalization – the app needs to make an HTTP POST for each page that is viewed to a URL similar to https://app.freshrelevance.com/app/v1/changeme/

Don't copy this exact URL – it needs to be configured for your account by replacing changeme with the account ID, from the drop-down menu at the top right of your account. If you're unsure, contact Support once your account has been created.

You should do an HTTP POST to the URL, with the JSON structure documented below in the body. You do not need to wait for any response to the POST - we recommend making an asynchronous request if supported by your app framework.

For example, your mobile app (or server connected to the app) should post a beacon of type 1 (PRODUCT_BROWSE) for every product page that is visited. With this beacon, you should supply details of the product(s) viewed and the cookie ID of the visitor.

You should use a separate Site Brand for your mobile app. This allows data to be used for cross-channel personalization and allow rules to check whether the data came from the website or from the mobile app.

Sample URL and sample of retrieved HTML:

Don't copy this exact URL – contact Fresh Relevance Support about how to access the correct URL for each Slot for your account.

This call returns a JSON structure like this:

{
"html": "",
"js": "",
"css": "",
"var": {},
"items": [{}, {}, {}],
"meta": {}
}

html is the rendered HTML from the SmartBlock template, based on the matching items.

items is a list of the products to be displayed by recommendation blocks.

Learn more


Slots, Rules, and Experiences for Native mobile apps

Your app can easily retrieve content from Fresh Relevance for use in the app by making an HTTP GET for each piece of content that is viewed. The content can be retrieved either in JSON format or in HTML format.

To personalize a web page or email, Fresh Relevance Slots are used. Each Slot is a location for content, and can be used on either a web page or an email. The content (SmartBlock) which is actually displayed by the Slot can be changed flexibly and at any time using content rules, configured using the Fresh Relevance UI. The same approach works for mobile app personalization as well.

We recommend having a separate slot for each distinct type of use, or perhaps for every place content is used in the app. This allows the rules to be used to change the content without having to add or remove slots.

The mobile app can make an HTTP GET request to the Fresh Relevance server and retrieve back either JSON or HTML representing the slot. This can then be rendered into the mobile app.

Experiences let you control content across multiple channels such as web, email and mobile app. There are various ways to use experiences with your mobile apps.


Fetching content for your Native App using the API

Content for your mobile app can be created in the same way as for Web personalization:

  1. Create a SmartBlock.

  2. Create a web Slot for the SmartBlock.

To get the exact URL to use in your app to request content for a slot with a GET request:

  1. Go to Content > Slots.

  2. Select a Slot, then select the Use icon.

  3. Select the Mobile App tab.
    Slots can be passed query collection parameters. These can be used within the Jinja2 script to change the generated HTML


Authentication

The mobile APIs require an API key or token to be passed in the x-api-key header.

This can be acquired from within the admin site: Expand the User menu and go to Settings > Other Integrations > Fresh Relevance Access Tokens > Create Token and select mobile for the Token Type.

JSON structure of beacon - generic

This is the full JSON structure and description of each field within a beacon. Not all elements are required for all page types.

Example payloads are available in the Postman documentation of the Mobile API.

The structure is also shared with the script that runs on a website with Fresh Relevance – you can view the data sent through the Site Info bar or by inspecting the WebSockets packets in Chrome Dev tools.

    {
"c": "Visitor Cookie ID",
"w": "Website ID",
"v": "Script Version Timestamp",
"epv": "Estimated Pageviews",
"configurable": "Boolean, if script is a configurable script",
"data": {
"typ": "Event Type",
"ptyp": "Page Type",
"ua": "User Agent",
"doc": {
"r": "Page Referer",
"u": "Page URL",
"t": "Page Title"
},
"pd": "Page Description",
"tmsd": {
"e": "Email Address",
"perm": "Email Marketing Permission true/false",
"s": "Session ID",
"nomail": "No Mail (deprecated and no longer actively used)",
"cid": "Customer ID"
},
"extend": {
"example": "Free form extra properties"
},
"lastsearch": "String, containing the last search terms",
"q": {
"example": "Whitelisted query parameters"
},
"cart": {
"qty": "Quantity",
"cp": "Cart Price, as shown to the user",
"rcp": "Regular Cart Price (e.g. before sale prices) optional",
"rcv": "Regular Cart Value (e.g. before sale prices) optional",
"cart_id": "Optional cart id",
"u": "Optional URL to get back to the cart (e.g. from an email)",
"curr": "Currency - ISO 4217 currency code e.g. GBP",
"cv": "Cart Value, as a number",
"sbr": "Site Brand/Territory for the product (e.g. the product was shown in USD on the US version of the store)",
"lang": "Language for the cart / session",
"ex": {
"example": "Extra properties for the cart"
},
"p": [
{
"n": "Product Name",
"qty": "Quantity",
"up": "Unit Price for the product (as seen by the user - e.g. sale price, offer price)",
"uv": "Unit Value for the product with no currency symbol",
"rup": "Regular Unit Price for the product (e.g. price before any sale or offer)",
"ruv": "Regular Unit Value for the product (e.g. price before any sale or offer)",
"img": "Large Product Image",
"img_tn": "Thumbnail Product Image",
"prid": "Product ID",
"sku": "Product SKU",
"rid": "ID used by review provider (if different from prid / sku)",
"pth": "Path of the product e.g. clothes/jumpers. Should only be used of the path is fixed for one product. Product ID / SKU preferred. Avoid.",
"desc": "Product Description",
"stock": "Integer Stock Level",
"curr": "Currency - ISO 4217 currency code e.g. GBP",
"cat": [
"Single String Value of Category name e.g. \"Shoes\"",
{
"n": "Category Name",
"g": "Category Group Name"
}
],
"subcat": [
"*Deprecated* Subcategory Array e.g. Trainers"
],
"ex": {
"example": "Extra properties for the product"
},
"opt": {
"example": "Personal options properties for the product (will not be merged into product database). e.g. size, colour, flight details"
},
"vid": "Variant ID added to the cart",
"variants": {
"[variant_id 1]": {
"vid": "Variant ID",
"sku": "Optional SKU of variant",
"stock": "Optional stock of variant",
"n": "Optional variant name override",
"img": "Optional variant image override",
"img_tn": "Optional variant thumbnail override",
"u": "Optional variant URL override",
"ex": "Optional variant extra data override",
"up": "Optional variant unit price override",
"uv": "Optional variant unit value override",
"rup": "Optional variant regular unit price override",
"ruv": "Optional variant regular unit value override",
"desc": "Optional variant description override",
"cat": "Optional variant category override. Will merge / replace matching categories"
}
},
"promo": "Array of selected promotion names (Note: Legacy scripts may pass in Boolean or other types)",
"sbr": "Site Brand/Territory for the product (e.g. the product was shown in USD on the US version of the store)",
"lang": "Language the product is displayed in",
"reviews": {
"rating": "The aggregated rating of a particular product",
"ratingCount": "The number of ratings that have been given to a particular product"
}
}
]
},
"p": [
{
"n": "Product Name",
"qty": "Quantity",
"up": "Unit Price for the product (as seen by the user - e.g. sale price, offer price)",
"uv": "Unit Value for the product with no currency symbol",
"rup": "Regular Unit Price for the product (e.g. price before any sale or offer)",
"img": "Large Product Image",
"img_tn": "Thumbnail Product Image",
"prid": "Product ID",
"sku": "Product SKU",
"rid": "ID used by review provider (if different from prid / sku)",
"review_locale": "Language Location (EN-GB/us etc)",
"reviews": {
"rating": "The aggregated rating of a particular product",
"ratingCount": "The number of ratings that have been given to a particular product"
},
"pth": "Path of the product e.g. clothes/jumpers. Should only be used of the path is fixed for one product. Product ID / SKU preferred. Avoid.",
"desc": "Product Description",
"stock": "Integer Stock Level",
"curr": "Currency - ISO 4217 currency code e.g. GBP",
"cat": [
"Single String Value of Category name e.g. \"Shoes\"",
{
"n": "Category Name",
"g": "Category Group Name"
}
],
"subcat": [
"*Deprecated* Subcategory Array e.g. Trainers"
],
"ex": {
"example": "Extra properties for the product"
},
"opt": {
"example": "Personal options properties for the product (will not be merged into product database). e.g. size, colour, flight details"
},
"promo": "Array of selected promotion names (Note: Legacy scripts may pass in Boolean or other types)",
"sbr": "Site Brand/Territory for the product (e.g. the product was shown in USD on the US version of the store)",
"lang": "Language the product is displayed in",
"vid": "Variant ID added to the cart",
"variants": {
"[variant_id 1]": {
"vid": "Variant ID",
"sku": "Optional SKU of variant",
"stock": "Optional stock of variant",
"n": "Optional variant name override",
"img": "Optional variant image override",
"img_tn": "Optional variant thumbnail override",
"u": "Optional variant URL override",
"up": "Optional variant unit price override",
"uv": "Optional variant unit value override",
"rup": "Optional variant regular unit price override",
"ruv": "Optional variant regular unit value override",
"desc": "Optional variant description override",
"cat": "Optional variant category override. Will merge / replace matching categories",
"ex": "Optional variant extra data override"
}
}
}
],
"s": "Session ID",
"eid": "External ID (prefixed eid)",
"e": "Email Address",
"cg": "Customer group (string)",
"mobile": "Mobile number in E.164 format or dict of number, code - where code is the 2 letter ISO country code",
"mediums": {
"sms": {
"perm": true,
"exclusion": false
},
"wa": {
"perm": true,
"exclusion": false
}
},
"b64e": "Base64 (or URL safe base64) version of the Email Address",
"rc4e": "RC4 encrypted Email Address",
"rsae": "RSA encrypted Email Address",
"nomail": "No Mail",
"sbr": "Site Brand/Territory for the page (e.g. the product was shown in USD on the US version of the store)",
"curr": "Currency - ISO 4217 currency code e.g. GBP",
"lang": "Language the site is displayed in",
"perm": "Email Marketing Permission true/false",
"co": {
"example": "Extra data for the completed purchase (e.g. order number)",
"o_num": "Order Number"
}
}
}

List of event types

The following is a complete list of the event types (typ in the above structure) that are supported by the API.

1

Page viewed, of type ptyp

7

Custom signal, for example, requested brochure, visited a certain page.

List of page types

The following is a complete list of the page types (ptyp in the above structure) that are supported for event type 1 (page view).

For a standard integration, only the pages highlighted in bold are required.

Constant name

ptyp value

Description

PRODUCT_BROWSE

1

Browse page for any shopping cart. Includes one product ID

LOGIN

2

Logging in to a shopping account

LOGIN_THANKS

3

After logging in to a shopping account

REGISTER

4

Register for a shopping account

REGISTER_THANKS

5

After register for a shopping account

CART

6

Cart page for any shopping cart. Includes 0 or more products

CHECKOUT

7

Cart page during the shopping process. Probably includes all carted products

PURCHASE_COMPLETE

8

Cart page after payment has been made. No products

PRODUCT_LIST

9

A Page with a list of products on it (e.g. a category page)

ACCOUNT_EDIT

10

Account settings page e.g. Magento account dashboard

NEWSLETTER_EDIT

11

Page where newsletter / mailing preferences are set / viewed

DNT_PREFERENCE

12

not a real page, used to send us Do-not-track / nomail -

CART_INPAGE

13

In page cart update (e.g. an ajax cart)

EMAIL_SEND

14

Email Send (e.g. UBX webhook)

EMAIL_OPEN

15

Email Open (e.g. UBX webhook)

EMAIL_CLICK

16

Email Clickthrough (e.g. UBX webhook)

POPOVER_SHOWN

17

Popover Shown, for Popover reporting

POPOVER_DISMISS

18

Popover Dismissed, for Popover reporting

POPOVER_SUBMIT

19

Popover Submitted, for Popover reporting

JSON example of beacon for page view

This is the full JSON structure to send to record a visit to a page.

Replace Website ID with the ID from the top right of your admin site. You should not include the comments on each line after //.

{
"type" : "beacon",
"data" : { // data type - always set to beacon
"e" : "test+john.lee.97264157+bh@example.net", // email address of person - supply this as and when known.
"mobile" : "+9998446272862", // mobile number
"w" : "Website ID", // this should be the ID of your client account.
"c" : "7q9kk23jpcihipdqv3xq1n5e5ydfkjn", // this should be a unique alphanumeric random ientifier for the deevice browsing the page. This should be set as a cookie for the end-user and persist across essions.
"doc" : {
"r" : "http://10.229.0.103/magento/index.php/no-referrer.html", // current page referer URL
"t" : "Shopping Cart", // current page title
"u" : "http://10.229.0.103/magento/index.php/checkout/cart/" // current page URL
},
"ip" : "96.44.94.103", // public IP address of the person browsing the page (useful for location based-marketing rules)
"typ" : NumberInt(1), //event type for a page view - see here for more info
"ptyp" : NumberInt(6), //the page type for product browse - see here for more info
"cart" : {
"cp" : "$300.40", // Text version of cart price, with currency symbol
"curr" : "USD", // currency used in the cart
"lang" : "en_us", // language
"u" : "http://10.229.0.103/magento/index.php/checkout/cart/", // url of the cart
"qty" : NumberInt(6), // number of entries in the cart.
"p" : [
{
"u" : "https://demo.freshrelevance.com/ski/skis/plastkon.html", // Product URL
"up" : "$50.00", // unit price of the product, in text format, with currency symbol.
"curr" : "USD", // currency
"sbr" : "US", // site brand
"lang" : "en_us", // language
"img" : "https://democdn.freshrelevance.com/pub/media/catalog/product/8/1/81azxbxgkbl._sl1500_.jpg", // image URL
"prid" : NumberInt(77), // product ID
"n" : "Plastkon", // product name
"sku" : "Plastkon", // product SKU
"qty" : NumberInt(3), // quantity of this line item
"variants" : null //optional array of variants
},
{
"u" : "https://demo.freshrelevance.com/k2-scene-women-s-snowboard-boots-2012-in-grey.html",
"up" : "$-59.60",
"curr" : "USD",
"sbr" : "US",
"lang" : "en_us",
"img" : "https://democdn.freshrelevance.com/pub/media/catalog/product/cache/1/image/1000x1320/e9c3970ab036de70892d86c6d221abfe/w/o/womens-boots-grey.jpg",
"prid" : NumberInt(56),
"n" : "K2 Scene Women's Snowboard Boots 2012 in Grey",
"sku" : "K2 SCENE WOMEN'S SNOWBOARD BOOTS 2012 IN GREY",
"qty" : NumberInt(1),
"variants" : null
},
{
"u" : "https://demo.freshrelevance.com/686-authentic-4eva-after-insulated-women-s-snowboard-2016-ivory-diamond-dobby.html",
"up" : "$105.00",
"curr" : "USD",
"sbr" : "US",
"lang" : "en_us",
"img" : "https://democdn.freshrelevance.com/pub/media/catalog/product/cache/1/image/1000x1320/e9c3970ab036de70892d86c6d221abfe/w/o/womens-jacket-ivory.jpg",
"prid" : NumberInt(64),
"n" : "686 Authentic 4eva-after Insulated Women's Snowboard 2016 Ivory Diamond Dobby",
"sku" : "686 AUTHENTIC 4EVA-AFTER INSULATED WOMEN'S SNOWBOARD 2016 IVORY ",
"qty" : NumberInt(2),
"variants" : null
}
]
},
"ua" : "Mozilla/5.0 (Windows; U; Windows NT 6.1; WOW64; en-US; rv:1.9.3a5pre) Gecko/20100609 Minefield/3.7a5pre ( .NET CLR 3.5.30729)", //user agent string of the person browsing the page
"serial" : NumberInt(1133), // optional, ignore if not sure
"src" : "PO"
},
"sbr" : "US", // site brand
"ud" : true // flag to indicate this packet has useful data. Always pass true.
}

JSON example of beacon for cart visit

This is the full JSON structure to send to record a visit to the shopping cart.

Replace Website ID with the ID from the top right of your admin site.

{
"type" : "beacon",
"data" : {
"e" : "test+john.lee.97264157+bh@example.net",
"mobile" : "+9998446272862",
"w" : "Website ID",
"c" : "7q9kk23jpcihipdqv3xq1n5e5ydfkjn",
"doc" : {
"r" : "http://10.229.0.103/magento/index.php/no-referrer.html",
"t" : "Shopping Cart",
"u" : "http://10.229.0.103/magento/index.php/checkout/cart/"
},
"ip" : "96.44.94.103",
"dcip" : "96.44.94.103",
"s" : "23840935",
"typ" : NumberInt(1),
"ptyp" : NumberInt(6),
"cart" : {
"cp" : "$300.40",
"curr" : "USD",
"lang" : "en_us",
"u" : "http://10.229.0.103/magento/index.php/checkout/cart/",
"qty" : NumberInt(6),
"p" : [
{
"u" : "https://demo.freshrelevance.com/ski/skis/plastkon.html",
"up" : "$50.00",
"curr" : "USD",
"sbr" : "US",
"lang" : "en_us",
"img" : "https://democdn.freshrelevance.com/pub/media/catalog/product/8/1/81azxbxgkbl._sl1500_.jpg",
"prid" : NumberInt(77),
"n" : "Plastkon",
"sku" : "Plastkon",
"qty" : NumberInt(3),
"variants" : null
},
{
"u" : "https://demo.freshrelevance.com/k2-scene-women-s-snowboard-boots-2012-in-grey.html",
"up" : "$-59.60",
"curr" : "USD",
"sbr" : "US",
"lang" : "en_us",
"img" : "https://democdn.freshrelevance.com/pub/media/catalog/product/cache/1/image/1000x1320/e9c3970ab036de70892d86c6d221abfe/w/o/womens-boots-grey.jpg",
"prid" : NumberInt(56),
"n" : "K2 Scene Women's Snowboard Boots 2012 in Grey",
"sku" : "K2 SCENE WOMEN'S SNOWBOARD BOOTS 2012 IN GREY",
"qty" : NumberInt(1),
"variants" : null
},
{
"u" : "https://demo.freshrelevance.com/686-authentic-4eva-after-insulated-women-s-snowboard-2016-ivory-diamond-dobby.html",
"up" : "$105.00",
"curr" : "USD",
"sbr" : "US",
"lang" : "en_us",
"img" : "https://democdn.freshrelevance.com/pub/media/catalog/product/cache/1/image/1000x1320/e9c3970ab036de70892d86c6d221abfe/w/o/womens-jacket-ivory.jpg",
"prid" : NumberInt(64),
"n" : "686 Authentic 4eva-after Insulated Women's Snowboard 2016 Ivory Diamond Dobby",
"sku" : "686 AUTHENTIC 4EVA-AFTER INSULATED WOMEN'S SNOWBOARD 2016 IVORY ",
"qty" : NumberInt(2),
"variants" : null
}
]
},
"ua" : "Mozilla/5.0 (Windows; U; Windows NT 6.1; WOW64; en-US; rv:1.9.3a5pre) Gecko/20100609 Minefield/3.7a5pre ( .NET CLR 3.5.30729)",
"serial" : NumberInt(1133),
"src" : "PO"
},
"sbr" : "US",
"ud" : true
}

JSON example of beacon to fire a custom signal

This document shows the full JSON structure to send to create a custom signal with namespace wishlist.

{
"type": "beacon",
"data": {
"w": "Website ID",
"c": "Visitor Cookie ID",
"v": "1234",
"typ": 7,
"ptyp": 0,
"ns": "wishlist",
"doc": {
"r": "https://www.mysite.com/product/10568/product-slug",
"t": "Wishlist | mysite.com",
"u": "https://www.mysite.com/wishlist"
},
"ip": "127.0.0.1",
"validate": true,
"trace": true,
"ignore_filters": true
}
}

If you need to send a cart and/or extra data with the custom signal, the format is as follows:

{
"type": "beacon",
"data": {
"w": "Website ID",
"c": "Visitor Cookie ID",
"ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36",
"v": "1397230569656",
"typ": 7,
"ptyp": 0,
"ns": "wishlist",
"cart": {
"p": [
{"prid": "acer-ferrari-3200-notebook-computer-pc", "vid": "putvidhere", "qty": 1, "sbr": "DEMO", "curr": "USD", "lang": "en_us", "up" : "$1799.99", "uv" : 1799.99},
{"prid": "chair", "vid": "putvidhere", "qty": 1, "sbr": "DEMO", "curr": "USD", "lang": "en_us", "up" : "$129.99", "uv" : 129.99},
{"prid": "htc-touch-diamond", "vid": "putvidhere", "qty": 1, "sbr": "DEMO", "curr": "USD", "lang": "en_us", "up" : "$750.0", "uv" : 750}
]
},
"extra": {
"a": "ba",
"b": "2015-01-12T15:56:28.706Z"
},
"doc": {
"r": "http://demostore.triggeredmessaging.com/?tms_ft=a4bicge",
"t": "HTC Touch Diamond",
"u": "http://demostore.triggeredmessaging.com/htc-touch-diamond.html"
},
"ip": "127.0.0.1",
"src": "WS"
},
}
  • Variants are optional - if not used in your account, remove "vid": "putvidhere".

  • Replace Website ID with the client account ID from the admin site.

  • The extra node is entirely optional and can be used to pass additional data attributes into the signal.

Variant data (optional)

Variant data is supported in the above specification. This is used when you have multiple variations of the same product, for example, different colours or sizes. You should specify all items that remain consistent in the root of the product. Each variant must have an ID that should be unique within the product.

For each variant to be recorded, include it in the variants dictionary, keyed by the variant ID. Each value should be an object. The optional values within are of the same type as in root of the product. There is a variant ID vid field within the root that allows you to specify which variant is being acted upon; browsed or added to a cart.

For example if you have two variants, red and blue, you may send an initial product browsed event for the red variant, followed by a second product browse event when the user selects the blue variant. If you specify a vid value, to signify which variant is being viewed, and you wish to pass base product values (for example, cat or ex), then you must pass an empty object to variants. For example, "variants": {}.


Reporting

Financial and performance reports are combined with data and purchases from web personalization and can be found in the main reports section of the platform.

Did this answer your question?