> Synerise Documentation — Web SDK > > This file contains the complete "Web SDK" section of the Synerise documentation. Each article begins with a top-level "# " heading. The manifest listing all sections is at https://hub.synerise.com/llms-full.txt # Getting started
We recommend creating the tracking code with the creator, as described in this article. However, if you're looking for the legacy method or need to edit an existing tracking code without the creator, see [Advanced tracking code settings](/developers/web/advanced-tracking-code).
## What is Synerise Web SDK Synerise Web SDK (Software Development Kit) is a JavaScript library that allows you to integrate Synerise on your website. This library (SDK) is responsible for data exchange between Synerise and the website into which it is implemented. Thanks to the SDK, we not only send data ([events](/docs/assets/events/event-definitions)) but also download data to show [dynamic content campaigns](/docs/campaign/dynamiccontent). The SDK is also responsible for customer identification, which means that SDK assigns a UUID for anonymous users on your website, if they already have a UUID, it recognizes them. If the visitor's User Agent matches any of those used by Googlebot, the SDK doesn't initialize. This means that Googlebot's page crawling visits don't generate any Dynamic Content, events, or Profiles. ### How to implement Synerise Web SDK? By [adding a tracking code into the source code of your website](#creating-a-tracking-code). ### What can the tracking code do? The tracking code's permissions are designed to be restrictive, so the code can be included in the source code of your website without risk to your infrastructure or the personal data of your visitors. It enables the following features: - You can display [Dynamic Content](/docs/campaign/dynamiccontent) on the page. Profile data, such as name or date of birth, can be added to the Dynamic Content with Jinjava inserts. Only the data of the profile whose UUID is stored in the cookies can be used. - You can send events. By default, [page.visit](/docs/assets/events/event-reference/web-and-app#pagevisit) events are tracked automatically. Other events can be sent with [declarative tracking](/developers/web/event-tracking#declarative-tracking-custom-events). - You can [identify users on your website](/developers/web/user-identification). When a visitor enters your site for the first time or after clearing their cookies, the SDK generates a random UUID and an anonymous profile is created. If that user becomes recognized (for example, by sending a login form), it may be [merged with an existing recognized profile](/docs/crm/merge). - Events sent by SDK requests can modify profiles if you allow it. To edit the list of events which can modify profile data, see [Event authentication settings](/docs/assets/events/event-settings). - The tracker key (part of the tracking code) can be used to authenticate customer-oriented requests to the [Recommendations](/developers/api/recommendations) and [Search](https://hub.synerise.com/api-reference/ai-search) APIs. This can be used to generate personalized recommendation and search results. - You can use [all methods provided by Synerise SDK](/developers/web/methods-reference). - You can also: - [track cart status](/developers/web/cart). - [send form data](/developers/web/tracking-form-data/tracking-form-data-sdk).
By default, sending form data with the SDK requires [JWT authentication](/developers/web/jwt-auth). If you want to change that, follow the instructions in ["Sending form data with JS SDK"](/developers/web/tracking-form-data/tracking-form-data-sdk).
- [send transaction events](/developers/web/transactions-sdk). - [send the status of newsletter agreements](/developers/web/newsletter-agreements#javascript-sdk). The code **can't be used to**: - Access the details or settings of your workspace. - Authenticate API requests, except for recommendation and search results. - Explicitly request personal data of customers. The SDK identifies the visitor by their UUID from the cookies. It can't access the visitor's Synerise profile directly (personal data from the profile can be displayed with Dynamic Content) or access the data of other profiles. ## Prerequisites - If you use a custom tracking domain, prepare DNS entries for it. See [Custom tracking domain](/developers/web/first-party-tracking). - Add the following domains to the allowlist in your Content Security Policy: - `*.synerise.com` - `*.snrcdn.net` - `*.snrbox.com` - If you use a custom tracking domain, you can skip this entry. - `*.snrlink-page.com` - `fcm.googleapis.com` - This is only required for Web Push. ## Creating a tracking code --- 1. Go to Settings icon **Settings > Tracking Codes > Add tracking code**. **Result**: The tracking code creation form opens.
Tracking code creation form
Tracking code creation form
2. In **Tracking code name**, enter the name. It's used for identifying the code on the list of tracking codes. 3. In **Domain name**, enter the domain where the code will be used. This setting **doesn't affect tracking or cookies** - its purpose is to identify the code. 4. Select the type of page where you want to implement the code.
If you choose **Single Page App**, you will need to manually implement page visit events and dynamic content after you include the tracking code in the page. This is described further in the article.
5. If you use Google data layer, enable the toggle and select the version. If your site uses multiple versions, you can only choose one for use with Synerise tracking. 6. If you use a custom tracking domain, enable **Custom domain tracking** and enter the domain in the field that appears.
Using a custom tracking domain requires additional configuration. See [Custom tracking domain](/developers/web/first-party-tracking).
7. This completes the basic settings. - If you don't need additional settings, continue to [Adding the tracking code to your site](#adding-the-tracking-code-to-your-site). - If you need additional settings, continue to [Additional options](#additional-options). ### Additional options
If you want to manually add these options to an existing tracking code, see [Advanced tracking code settings](/developers/web/advanced-tracking-code).
1. Expand **Additional options**. 2. Configure the settings that you need: #### Custom cookie expiration time By default, cookies expire after 400 days. To change the expiration time, enable the toggle and enter the period. #### Override cookie domain If you use several subdomains, they generate cookies with their own domain. To declare a specific domain instead, enable the toggle and enter the domain. #### Disable automatic tracking of page visits You can disable automatic collection of `page.visit` events. You can re-implement the events by using the [SDK methods](/developers/web/event-tracking).
For Single-Page Applications, this option is always enabled.
#### Custom service worker scope If you use Synerise Web push notifications and need to set a custom service worker scope (registration path), enable the toggle and enter the path. #### Customizing metadata You can add `` tags (for example, OG tags) to the website or modify existing ones. The new values are added to `page.visit` events. They can also be used with other features based on metadata, such as communication, recommendations, personalization, and so on. To add the metadata, enable the toggle and paste JS code inside the `function (metadata)` function.
If you chose **Shopify** as the page type, a piece of Jinjava required for the integration is already added to the metadata and this option can't be disabled.
**Example**:
function (metadata) { // DO NOT REMOVE
    metadata.size = 8;
    metadata.isExample = true;
    metadata['og:title'] = 'Sneakers';
    metadata['product:retailer_part_no'] = '1a4d3380-04d1';
    return metadata; // DO NOT REMOVE
    }                // DO NOT REMOVE
Syntax usage: - If the name of the meta key doesn't contain special characters, use the `metadata.keyName = 'keyValue'` syntax. - If the name of the meta key contains special characters, use the `metadata['key_name'] = 'keyValue'` syntax. - Up to 20 meta parameters can be returned. - The following value types are allowed: - string - number - boolean - array #### Manage some Synerise features You can turn off Web push notifications and/or Dynamic Content by disabling the toggles. The feature or features will be disabled entirely for this tracking code and **can't be restored with SDK methods**. ## Adding the tracking code to your site 1. After you complete the configuration, click **Generate**. **Result**: The tracking code is generated and displayed.
A screenshot of a generated tracking code
An example generated tracking code for a Web page
2. Continue depending on the selected page type:
1. Copy the tracking code. 2. Paste the code into your website, before the closing `` tag. You can use Google Tag Manager to do this (when using a custom tracking domain this is **not** recommended). 3. If you enabled the custom tracking domain, make sure it's added to the DNS and API methods as described in [Custom tracking domain](/developers/web/first-party-tracking).
1. Copy the tracking code. 2. Paste the code into your website, before the closing `` tag. You can use Google Tag Manager to do this (when using a custom tracking domain this is **not** recommended). 3. If you enabled the custom tracking domain, make sure it's added to the DNS and API methods as described in [Custom tracking domain](/developers/web/first-party-tracking). 3. Re-enable page visit tracking and Dynamic Content retrieval by implementing the following methods in the page:
SR.event.pageVisit()
          .then(function () {
              SR.dynamicContent.get();
      })
Page visits and dynamic content retrieval must be implemented according to the following rules: - og:tags must be loaded first, regardless of the method that is used to load them. - page visits and dynamic content must be requested whenever the page is loaded, reloaded, and when the view changes.
You can use Google Tag Manager to implement the methods. To do so, trigger `SR.event.pageVisit();` and `SR.dynamicContent.get();` methods on events that indicate a page or DOM being loaded. `SR.init` is only called when DOM is loaded.
For VTEX, 2 variants of the tracking code are generated. 1. Add the codes to the VTEX pages as described in [Integration for stores using Store Framework](/docs/settings/tool/vtex/vtex-integration). 2. If you enabled the custom tracking domain, make sure it's added to the DNS and API methods as described in [Custom tracking domain](/developers/web/first-party-tracking).
For Shopify, 2 variants of the tracking code are generated. 1. Add the tracking code to the Shopify page according to the [Shopify integration instructions](/docs/settings/tool/integrating-shopify-with-synerise#implement-tracking-codes-in-your-shop). 2. If you enabled the custom tracking domain, make sure it's added to the DNS and API methods as described in [Custom tracking domain](/developers/web/first-party-tracking).
## Nonce for Content Security Policies Nonce (number used once) is a content attribute which can be used by Content Security Policies (CSPs) to determine if an element should be allowed. If a script doesn't have a nonce value that matches the one expected by the CSP, the script can't execute. You can add the nonce to the Synerise SDK initialization script:
SR.init({
  trackerKey: "VALUE",
  nonce: "VALUE"
});
The tracking code and any scripts that the SDK adds to the page (for example, in Dynamic Content) will have the nonce value that you add to `SR.init`
You must generate the value of the nonce yourself and make sure it matches the one expected by the CSP.
For more details on nonce and implementing it, see [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce). # Customer identification
**Upcoming breaking change (effective July 6, 2026):** Synerise is introducing changes to how user identifiers and UUIDs are handled. These changes may affect profiles with accented or diacritical characters in identifiers, profiles with leading or trailing whitespace in identifiers, and profiles with duplicate UUIDs. For details and recommended actions, see [Upcoming changes to handling identifiers](/docs/settings/configuration/identifier-standardization).
## Anonymous customers When a customer enters your website for the first time, they are anonymous. However, their actions are already being tracked - a UUID is assigned and stored in an anonymous profile in the database. The same UUID is stored in the [cookies](/developers/web/cookies) of the customer's browser. The anonymous profile stores information about the customer's activities, just like it does for recognized customers. The customer can now receive personalized recommendations on the website and be included in marketing campaigns. ## Recognized customers By default, the unique identifier is the customer's `email`. You can [configure your workspace to use `customId` instead](/docs/settings/configuration/non-unique-emails). In the Web SDK and some other contexts (for example, form tracking), `customId` may also be referred to as `custom_identify`. When the customer provides the unique identifier, the anonymous profile in the database is updated with new data. It becomes a known customer profile, which means that any activity before the customer was recognized is still present in the profile's history. A freshly-recognized customer sees personalized content, based on their previous interactions with the website as an anonymous customer. If a recognized customer provides a unique identifier in a form, and another recognized customer's profile already exists in the browser, the context changes to the most recent customer.
It's not necessary for a customer to register an account on your website. A non-anonymous profile may be created based on information provided in other contexts, such as subscribing to a newsletter. See [Tracking form data with SDK](/developers/web/tracking-form-data), [Newsletters](/developers/web/newsletter-agreements), and [Tracking form data with API](/developers/web/tracking-form-data/tracking-form-data-api).
## Recognizing customers from link parameters --- You can append parameters to links to inform the Synerise JS SDK who clicked the link. The parameters are `snrs_cl` (the user's UUID) and `snrs_he` (hash of the user's identifier). A [tracking code](/developers/web/installation-and-configuration) must be implemented in the linked page. The instructions on adding the parameters to the links in templates are available at the links below: - [Email templates](/docs/campaign/e-mail/creating-email-templates#tips-before-you-start) - [Mobile push templates](/docs/campaign/Mobile/creating-mobile-push-templates/mobile-push-visual-builder#adding-tracking-parameters-to-links) - [SMS templates](/docs/campaign/SMS/creating-SMS-template#tracking-parameters-in-links) - [Web push templates](/docs/campaign/Webpush/creating-webpush-templates#tracking-parameters-in-links) When these parameters are present in a link, the user’s browser context is automatically switched to the identified user without any prompt. The primary purpose of this automatic context update is to maintain continuity of the user’s journey after clicking the link—for example, from an email campaign—ensuring that all subsequent [events](/docs/assets/events/introduction-to-events) are accurately attributed to the user whose identifier was included in the link. This mechanism enables seamless user journey continuity but can also lead to context changes when a link is shared with another person. In such cases, the recipient’s browser context will switch to that of the original user, which may affect how events are attributed. On the user interface on the Synerise platform, you can decide how end-user context is managed when these link parameters are detected; the full instruction is available in the ["Managing user context" section](/docs/settings/configuration/non-unique-emails#managing-user-context). # Synerise storage Synerise SDK uses several different cookies that store customer data. ## Cookies ### Expiration time By default, the `_snrs_p`, `_snrs_uuid`, and `_snrs_puuid` cookies expire after 400 days. You can change this by using the `cookieExpiration` parameter. The value is the number of days after which the cookies expire.
- If a browser's cookie expiration limit is lower than your setting, your setting is ignored. - The expiration time of the `_snrs_sa` and `_snrs_sb` cookies is 30 minutes and **cannot** be changed.
The following example sets cookie expiration time to 60 days:
SR.init({ 
    "trackerKey": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "cookieExpiration": 60
});
### _snrs_p This cookie stores general information about the customer. | Field | Description | |:-------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | host | The owner's domain address | | ~~permUuid~~ | This field is deprecated. Do not use it. | | uuid | A randomly generated customer UUID. This value cannot be used to identify a customer until they provide more information. | | identityHash | If the customer provided an email address, the value is hashed and the hash is then used to compare email addresses provided during subsequent visits. If the email address changes, a new UUID is generated for the customer. | | user_hash | If the *_ush* cookie is set, the value is stored here. In the _ush key, you can keep the id of the customer logged in to the owner's website. Thanks to this parameter, Synerise is able to link these two identifiers. | | init | The time of the first page visit (time from the customer's browser) | | last | The time of the most recent page visit | | current | The current time | | uniqueVisits | The number of unique page visits | | allVisits | The total number of all page visits | ### _snrs_params This cookie stores all `_snrs_` parameters attached to URLs (such parameters can be added to a link when a visitor to a website clicks a recommendation or dynamic content) for 3 days. If the visitor makes a transaction within this period, the `_snrs_` parameters will be added to [transaction events](/docs/assets/events/event-reference/items) sent through JS SDK thanks to [DataLayer integration](/developers/web/installation-and-configuration). ### _snrs_sa This cookie stores information about the current session. Each session lasts 30 minutes. | Field | Description | |:--------------|:-----------------------------------------------| | ssuid | A customer session ID | | appear | The start time of the current session | | sessionVisits | The number of page visits during this session | ### _snrs_sb This cookie stores information about the time when the customer left the page. | Field | Description | |:-------|:------------------------------------| | ssuid | A customer session ID | | leaves | The end time of the session | ### _snrs_sdk_d Special-purpose cookie for Synerise. It's not created automatically. Expiry time is set when the cookie is created. ### _snrs_uuid This cookie stores the customer's UUID (may differ between devices). ### _snrs_puuid Deprecated. This cookie stores the customer's permanent UUID. ### _snrs_cid This cookie stores the ID of a DC campaign. Expires after a year. ### _snrs_dc_sd This cookie stores information about the time when a dynamic content campaign should stop displaying. ### _snrs_dc_views_sd This cookie stores information about the number of views after which a dynamic content campaign will no longer be displayed. ### _snrs_notify_delay Deprecated. This cookie stores information about the delay before showing a notification. ### _snrs_notify_capping Deprecated. This cookie stores information about the maximum number of times a notification is to be displayed. ### _snrs_reset_uuid This is a special purpose cookie that allows you to [assign customer UUIDs](/developers/web/uuids#resetting-customer-uuids). ### _snrs_reset_uuid_and_identity_hash This session cookie allows you to set the UUID and identity hash of a website visitor, overriding the default mechanism of assigning a random identifier. - The cookie stores the visitor's UUID and identity hash in plain text format (for example, `87d3c1eb-0d1d-4749-8845-27f4b085d7ff:thisIsYourHash`). When present, it instructs the Synerise SDK to use these values, thereby resetting the visitor's identification within the SDK. - The cookie `_snrs_reset_uuid_and_identity_hash` must be set as a session cookie, valid only for the duration of the browser session. The SDK reads (retrieves data from) this cookie and, by default, clears (deletes) it after use, ensuring it expires when the session ends. - This cookie is not automatically created by the SDK. You must create a mechanism that creates the cookie, with the correct domain. ## Synerise local storage Additionally, Synerise SDK uses several local storage keys that store customer data. ### _snrs_dc_delay This key stores information about the delay before showing a dynamic content campaign. ### _snrs_dc_frq This key stores information about the frequency of checking if a dynamic content campaign has expired. Cleared when browser data is cleared. ### _snrs_dc_tests This key stores an array of dynamic content variants if A/B testing was applied in dynamic content campaigns. ### _snrs_profile_config This is an object stored in browser's localStorage. This object contains settings of the [workspace](/docs/settings/workspace) from which the tracking code is implemented into the website. The objects store the following information: | Field | Description | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | recognizeBy | This key stores the name of the attribute based on which the visitor to the website is recognized when form tracking is enabled based on the JS SDK methods. Possible values: `email` and `custom_identify`. You can indicate this attribute in [the Synerise platform](/docs/settings/configuration/non-unique-emails). | | ~~profile~~ | This key is deprecated. Do not use it.
This key stored the subdomain (a random string of characters) generated automatically for the workspace when the workspace was created. This subdomain was used by JS SDK for integrating web push notifications. | | dataMarker | This key is deprecated for the new workspaces. Do not use it.
This key stores the configuration for form integration on the website. This key is available for old workspaces. | | providers | This object is required for notification integration (such as web push). Data in this object is necessary for communication between Synerise and Firebase. | | signedIdentifiedActions | This key contains an array of [events which require JWT authentication](/docs/assets/events/event-settings) as a result of JS SDK implementation. | | ~~notifications~~ | This key is deprecated.
This key contained an array of dynamic content campaigns that had been displayed to the visitors to the website. | | ~~cookieMatchers~~ | This key is deprecated.
This key contained the configuration that enabled cookie matching. | | snrsProfileConfigExpire | This key contains the time when the `_snrs_profile_config` object will be retrieved again. | ### synerise-traffic-storage This is a JSON object that contains all requests sent from the website to a tracker. The data is stored in case of a network failure so the SDK can retry sending later. Cleared when browser data is cleared. #### How does it work? 1. JS SDK sends an event, for example [page.visit](/docs/assets/events/event-reference/web-and-app#pagevisit). 2. An entry is created with a randomly generated UUID ([synerise-traffic-storage-UUID](#synerise-traffic-storage-uuid)). This entry contains the request to API. 3. If the request is successful (response 200), the entry with the request is removed. If the request cannot be executed (for example, due to temporary network failure), the request is kept in the entry and executed at the nearest opportunity. ### synerise-traffic-storage-UUID This key stores UUIDs under which requests from the website to a tracker are saved. ### synerise-form-catch This key stores information from submitted forms that has not been saved in Synerise (for example, due to temporary network failure). Cleared when browser data is cleared. ### snr-wp-state This key stores the current status of the web push module. Cleared when browser data is cleared. | Field | Description | |:------------------|:-------------------------------------------------------------------------------------------------------------------| | permission | Informs about the the browser's notification permission setting | | permissionSaved | Informs if the permission has been saved | | subscription | Informs about the customer's consent in Synerise to receive web-push notifications | | subscriptionSaved | Informs if the subscription has been saved | | tokenHash | The token for the current web-push status | | tokenTime | Timeout for the token of the permissionSaved status. Permission saved will be set to **false** after the timeout. | | uuid | The customer's UUID | ### snr-token Stores the [JSON Web Token](/developers/web/jwt-auth) used for customer authentication. Cleared when browser data is cleared. # Event tracking The JS SDK tracks customer activity as events and sends them to Synerise in real time. Page views and sessions are tracked automatically. You can also send custom events for any action you want to record. Every event consists of an `action` in the form `context.activity` (for example, `page.visit`) and optional parameters. The SDK automatically enriches every event with browser and tracker context, even when no parameters are explicitly passed. For the list of these parameters, see [Common parameters](/docs/assets/events/event-reference/common-parameters). ## Authentication Requests to the SDK may require customer authentication. For more details, see [this article](/developers/web/jwt-auth). ## Automatically tracked activities Page view and session events are tracked automatically, unless configured otherwise (see [Getting started](/developers/web/installation-and-configuration)). Each time a page is refreshed, the tracking code is initiated and a `page.visit` event is generated. For single-page applications that do not refresh between pages, you must send `page.visit` on demand - see ["Send a page.visit event" method](/developers/web/methods-reference#send-a-pagevisit-event). ### List of automatically tracked activities The following events are tracked by default: | Action | Activity Tracked | Label | |:--------------|:------------------------------------------------|:----------------------------| | [page.visit](/docs/assets/events/event-reference/web-and-app#pagevisit) | All page views of your tracked domain | Visited page {{page title}} | | [session.start](/docs/assets/events/event-reference/web-and-app#sessionstart) | Information about a customer starting a session | Started session | | [session.end](/docs/assets/events/event-reference/web-and-app#sessionend) | Information about a customer ending a session | Session end | When Google Data Layer is configured, the following events are tracked in addition to the defaults above - see [Transactions and basket events](/developers/web/transactions-sdk) for setup details: | Action | Activity Tracked | |:-----------------------|:--------------------------------------------------------------------------| | [product.addToCart](/docs/assets/events/event-reference/items#productaddtocart) | Product added to cart | | [product.removeFromCart](/docs/assets/events/event-reference/items#productremovefromcart) | Product removed from cart | | [transaction.charge](/docs/assets/events/event-reference/items#transactioncharge) | Purchase recorded | | [product.buy](/docs/assets/events/event-reference/items#productbuy) | One event per purchased item (created together with `transaction.charge`) | ## Declarative tracking (custom events)
DO NOT use custom events for `transaction.charge` events. Transactions must be tracked as described in [Transactions and basket events](/developers/web/transactions-sdk).
Use custom events to track any customer action not covered by automatic tracking, such as button clicks or form submissions.
When using the JS SDK, you can only send custom events that are defined in [**Data Modeling Hub > Events**](/docs/assets/events/event-definitions) and have at least the **Make this event available to anonymous profiles without JWT** option selected in their permission settings.
Events with action names that are not defined in the system are rejected.
**Example:**
SR.event.trackCustomEvent(
    "button.click", // event action name
    { // optional parameters — define your own
        "customParam1": "value1",
        "customParam2": "value2",
        "time": 1556474400000 // if provided, the event is recorded in the past with this timestamp; if omitted, the SDK sets the timestamp automatically
    }
)
The method takes two arguments: + The name of the action (line 2) + An object that contains optional event parameters (lines 3-7)
- The action name must follow the `context.action` convention. For example: `button.click`, `social.share` - The action name must be up to 32 characters long and must match the following regular expression: ``` ^[a-zA-Z0-9\.\-_]+$ ```
# Sending form data with JS SDK
**Upcoming breaking change (effective July 6, 2026):** Synerise is introducing changes to how user identifiers and UUIDs are handled. These changes may affect profiles with accented or diacritical characters in identifiers, profiles with leading or trailing whitespace in identifiers, and profiles with duplicate UUIDs. For details and recommended actions, see [Upcoming changes to handling identifiers](/docs/settings/configuration/identifier-standardization).
## Introduction If you have embedded the Synerise [tracking code](/developers/web/installation-and-configuration) in your website, you will see anonymous customers in the Synerise Dashboard. In this section, you will learn how to track forms on your website. Capturing forms is crucial, as the data used there automatically updates an anonymous customer's information and turns them into a known contact. The data is saved in a [form.submit event](/docs/assets/events/event-reference/web-and-app#formsubmit). The event contains all data from the form.
By default, tracking a form requires authentication and cannot be used by anonymous customers. To change this, modify the event authentication settings: 1. Add `form.submit` to the [list of events which do not require JWT authentication](/docs/assets/events/event-settings#events-which-change-customer-data-and-dont-require-authentication). 2. Remove `form.submit` from the [list of events which require JWT authentication](/docs/assets/events/event-settings#events-which-change-customers-data-and-require-authentication).
You probably have several types of forms on your page, such as a login, contact, or registration form, or one for leaving comments. This provides a variety of data, from a customer's first name to their comment about a product or your business. Synerise needs to know what type of data is sent in each input, so it can update the customer's personal data properly. ## Managing user context Sending form data allows you to manage user context (UUID) in the browser. You can choose which identifying attribute (`email` or `custom_identfy`) to use for managing user context. The available identifiers differ depending on the selected configuration for email address uniqueness (see [Identifiers](/docs/settings/configuration/non-unique-emails)). If you use: - unique emails - then you can [define the identifier for managing user context](/docs/settings/configuration/non-unique-emails#managing-user-context). Once selected, you must consistently use it when sending form data.
If you send an identifying attribute that isn’t set as the context manager, it will be treated like a custom attribute and added or overwritten. For example, if `custom_identify` is set as the user context identifier and you send a different email address, the email will update but the user context remains unchanged.
- non-unique emails - then `custom_identify` is the only available identifying attribute.
You can decide how the user context is handled [when a link contains user-identifying parameters (snrs_cl and snrs_he)](/developers/web/user-identification#recognizing-customers-from-link-parameters).
### Context managing behavior - **For an anonymous user** - sending form data with an identifying attribute will recognize the user without changing their UUID. If a profile with that identifier already exists, the UUID will be [merged into the existing profile](/docs/crm/merge). - **For a recognized user** (different from the one provided in the form data): the user’s UUID is reset, and the browser context is updated to match the data sent in the form. If a profile with the given identifier already exists, the UUID will be [merged into that profile](/docs/crm/merge). ## Sending data to Synerise with HTML form attributes To send data from a form to Synerise, the form's fields must have the `data-synerise` attributes added to them.
The SDK does not validate the data. For example, if the customer makes an error in their identifier and sends the form, a new profile with that identifier is created. This may cause the event history of an anonymous customer to be merged into a recognized profile with an error in the identifier, even if the user re-sends the form again with the right identifier. To avoid this, validate the entered data before sending the form.
**Example:**
<form action="" method="post" data-synerise="contact">
    <input type="text" name="email" data-synerise="email" placeholder="Email" value="john.doe@synerise.com" />
    <input type="text" name="name" data-synerise="firstname" placeholder="Name" value="John" />
    <input type="text" name="surname" data-synerise="lastname" placeholder="Surname" value="Doe" />
    <input type="text" name="customParam2" data-synerise="customAttribute1" value="customValue2" />
    <input type="hidden" name="customParam2" data-synerise="customAttribute2" value="customValue2" />
    <input type="submit" value="Save" />
</form>
In the `form` tag, in the `data-synerise` attribute, you can send several values, separated by commas (`data-synerise="value1,value2,value3"`). The values will be saved in the event data as `formType` and as tags in the customer's card in **Behavioral Data Hub > Profiles**. You can add additional attributes (see `customAttribute` in the example). They are saved to the `attributes` object in a customer's profile. When the form above is sent, the following call to the SDK is made **automatically**:
SR.event.sendFormData('contact',
    { //form data
        "surname": "Doe",
        "name": "John",
        "email": "john.doe@synerise.com",
        "customParam1": "customValue1",
        "customParam2": "customValue2"
    },
    { //field mapping
        "lastname": "surname",
        "firstname": "name",
        "email": "email",
        "customAttribute1": "customParam1",
        "customAttribute2": "customParam2"
    }
)
**Explanation**: + Form data: _object_, HTML form field values. These are the collected values that are sent to Synerise and potentially stored as customer information in the customer card in **Behavioral Data Hub > Profiles**, depending on the mapping. + Field mapping: _object_. This object provides the mapping between the `name` attributes of your HTML form fields and the predefined fields of the customer object in the Synerise system. ### Delayed data forms If an HTML form with `data-synerise` attributes appears after the tracking code has been initialized (for example, in a pop-up window), you have to explicitly initialize another search for the attributes on the page, using the following SDK method:
SyneriseTC.initFormCatch()
## Calling the SDK directly If you use the SDK method directly, you do not need to include the mapping object. You can refer to the fields directly by their Synerise names:
- If you use the non-unique email feature, use `custom_identify` instead of `email`. See [non-unique email feature configuration](/docs/settings/configuration/non-unique-emails). - The SDK does not validate the data. For example, if the customer makes an error in their identifier and sends the form, a new profile with that identifier is created. This may cause the event history of an anonymous customer to be merged into a recognized profile with an error in the identifier, even if the user re-sends the form again with the right identifier. To avoid this, validate the entered data before sending the form.
SR.event.sendFormData('formType', {
    lastname: "Doe",
    firstname: "John",
    email: "john.doe@synerise.com",
    customAttribute: "customAttributeValue" // saved in the `attributes` object of a Profile
    // more attributes and custom attributes
})
You can replace `formType` with another value or a number of comma-separated values (no spaces). These values are saved as `formType` in the event and as tags in the customer's Profile. ### Sending multiple events When calling the SDK directly, you may want to send more events with the `form.submit` event. To ensure that those additional events are saved after `form.submit` identifies the profile, use the `then` function. For example, if you want to add a `review.send` event to the `form.submit` event:
SR.event.sendFormData('formType', {
    lastname: "Doe",
    firstname: "John",
    email: "john.doe@synerise.com",
}).then(function () {
    SR.event.trackCustomEvent("review.send",
        {
            "stars": 5
        });
});
## Marketing agreements See [Newsletter agreements](/developers/web/newsletter-agreements). ## Recognizing already logged users You can automatically recognize users who have logged in previously and their session is still active. ### Requirements ID of a currently logged-in user: - if you use unique emails: `email` or `custom_identify` - if you use [non-unique emails](/docs/settings/configuration/non-unique-emails): `custom_identify` ### Methods Execute the following methods in a given order: 1. [Get IdentityHash](/developers/web/methods-reference#get-identityhash) - This method generates and saves automatically `IdentityHash` based on: - ` email ` or `custom_identify` (for unique emails), - ` custom_identify ` (for non-unique emails). 2. [Calculate IdentityHash](/developers/web/methods-reference#calculate-identityhash) - This method calculates `IdentityHash` for any string. 3. [Send form data](/developers/web/methods-reference#send-form-data) - This method recognizes a user. ### Responses
SR.client.getIdentityHash(): String //if there is no identity hash, an empty string is returned
SR.client.hashIdentity(email): Number
### Example implementation The following code snippet compares the data about the currently tracked user with an email of a logged user. It checks whether the user is unidentified in Synerise or if the logged account is different from the one associated with the provided email. If either condition is met, the code proceeds to send form data for a login event, including the captured email, along with any additional parameters as key-value pairs.
//capture logged user email
const email="john.doe@synerise.com"

//user logged but unidentified in Synerise or logged identified as different account
if(email && (SR.client.getIdentityHash()==='' || SR.client.getIdentityHash()!==SR.client.hashIdentity(email))){
    SR.event.sendFormData('login', {
        email: email
        //additional parameters as key-value pairs
    })
}
# Sending form data with API
**Upcoming breaking change (effective July 6, 2026):** Synerise is introducing changes to how user identifiers and UUIDs are handled. These changes may affect profiles with accented or diacritical characters in identifiers, profiles with leading or trailing whitespace in identifiers, and profiles with duplicate UUIDs. For details and recommended actions, see [Upcoming changes to handling identifiers](/docs/settings/configuration/identifier-standardization).
Form data is usually [tracked by using the SDK](/developers/web/tracking-form-data), but you can make API calls from your backend, so that you have more control over the process and access to detailed event logs. Unlike the SDK, the logic of calling endpoints can also be modified according to business requirements.
The API calls must be made by the server! Making API calls from the browser exposes your API key.
The logic described in this article will let you detect if the customer who fills in a form (for example, a log-in form) is the same as the one currently recognized in the browser. The data is saved in a `form.submit` event. The event contains all data from the form.
If you implement tracking form data over the API, it is recommended to block sending form.submit events by the SDK. See [Event authentication settings](/docs/assets/events/event-settings).
To learn more about our API, see [these articles](/developers/api). ## Implementation overview The flowchart presents an overview of the logic which replicates the behavior of tracking form data over the SDK. In certain conditions, some steps of the logic are redundant. Thanks to this, all scenarios are covered with inserting additional checks.
Depending on your configuration, the unique identifier is email (default setting) or custom ID (see [Identifiers](/docs/settings/configuration/non-unique-emails).)
This logic is a suggestion. You can modify it according to your business needs or create your own. Remember to cover all the scenarios.
Sending form data with API
Overview of tracking form data by using the API
## Implementation details This section explains in detail the flow of events and actions, and how to implement them. ### Customer enters site and fills in HTML form HTML form example:
<form action="" method="post">
    <input type="text" name="email" placeholder="Email" value="john.doe@synerise.com" />
    <input type="text" name="name" placeholder="Name" value="John" />
    <input type="text" name="surname" placeholder="Surname" value="Doe" />
    <input type="submit" value="Save" />
</form>
1. Gather data from the HTML form. 2. **Optional:** Validate the data in the form (for example, check if email is properly formatted). 3. **Optional:** Authenticate the customer. 4. Check if the `_snrs_p` cookie has a value for `identityHash`. **`_snrs_p` cookie example:**
_snrs_p:
       host:
       permUuid:e0097757-d1e2-44ac-ba3c-d97979a354c1 # deprecated
       uuid:e0097757-d1e2-44ac-ba3c-d97979a354c1 # current UUID
       identityHash:277163923
       init:1613135695
       last:1625149870.406
       current:1625149875
       uniqueVisits:7
       allVisits:17
1. Perform one of the following actions: - if `identityHash` does not have a value, proceed to [this section](#if-identityhash-does-not-a-have-a-value). - if `identityHash` has a value, proceed to [this section](#if-identityhash-has-a-value). ### If identityHash does not a have a value The customer is currently anonymous. The data from the anonymous account needs to be associated with the data for the customer who filled in the HTML form. 1. Generate an UUIDv5 for the customer. For details, see [this article](/developers/web/uuids#generating-uuidv5). 2. Send a create/update API call to merge the anonymous customer with the one who was identified in the HTML form. The request body must contain an array with two objects: one with the identifier and the new UUIDv5, the other with the identifier and the UUID from the `_snrs_p` cookie. API reference is available [here](https://hub.synerise.com/api-referenceClientManagement/ClientManagement.html#operation/BatchAddOrUpdateClients). If you want to send additional data, such as agreements or free-form attributes, they must be included in the object with the new UUIDv5.
See curl example (email)

The highlighted properties are required, the others are optional. For a comprehensive list of properties you can send, see API reference.

curl --location --request POST '{SYNERISE_API_BASE_PATH}/v4/clients/batch' \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'Api-Version: 4.4' \ --header 'Authorization: Bearer eyJ...yeIc' \ --data-raw '[ { "email": "example@synerise.com", "uuid": "4f82f7a9-0745-55a3-b028-e301b19bf8ec", "agreements": { "email": true, "sms": true }, "tags": [ "exampleTag" ], "attributes": { "customAttribute1": true, "customAttribute2": "string", "customAttribute3": 42 } }, { "email": "example@synerise.com", "uuid": "35a1c1d8-2468-4c47-9be2-f2c2edf9f526" } ]'
See curl example (customId)

The highlighted properties are required, the others are optional. For a comprehensive list of properties you can send, see API reference.

curl --location --request POST '{SYNERISE_API_BASE_PATH}/v4/clients/batch' \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'Api-Version: 4.4' \ --header 'Authorization: Bearer eyJ...yeIc' \ --data-raw '[ { "customId": "example.customId", "uuid": "d2bdec3a-96d9-5805-9ca2-1557aec691b1", "agreements": { "email": true, "sms": true }, "tags": [ "exampleTag" ], "attributes": { "customAttribute1": true, "customAttribute2": "string", "customAttribute3": 42 } }, { "customId": "example.customId", "uuid": "35a1c1d8-2468-4c47-9be2-f2c2edf9f526" } ]'
1. Send a `form.submit` event. The data from the form is stored in the `params` object. API reference is available [here](https://hub.synerise.com/api-reference/data-management#operation/CustomEvent).
See curl example (email)
curl --location --request POST 'https://{SYNERISE_API_BASE_PATH}/v4/events/custom' \ --header 'Authorization: Bearer eyJh...T-hyeIc' \ --header 'Api-Version: 4.4' \ --header 'Content-Type: application/json' \ --data-raw '{ "label": "Customer submitted a form", "action": "form.submit", "client": { "email": "example@synerise.com" }, "params": { "firstname": "John", "lastname": "Doe", "formType": "exampleFormType" } }'
See curl example (customId)
curl --location --request POST 'https://{SYNERISE_API_BASE_PATH}/v4/events/custom' \ --header 'Authorization: Bearer eyJh...T-hyeIc' \ --header 'Api-Version: 4.4' \ --header 'Content-Type: application/json' \ --data-raw '{ "label": "Customer submitted a form", "action": "form.submit", "client": { "customId": "example@synerise.com" }, "params": { "firstname": "John", "lastname": "Doe", "formType": "exampleFormType" } }'
4. Store the new UUIDv5 in the browser in one of the following ways: - If after SDK initialization: use the `SR.client.setUuid("new_uuid");` method; replace `new_uuid` with the UUID. The UUID is written to the `_snrs_p` cookie immediately. - If the Synerise SDK is not initialized, store the UUID in the `_snrs_reset_uuid` cookie. The UUID is written to the `_snrs_p` at SDK initialization. **Result:** The customer's data is saved, a recognized profile is created. ### If identityHash has a value The customer is recognized. You need to check if the customer who filled in the HTML form is the same as the one whose data is currently saved in the `_snrs_p` cookie. 1. Generate the `identityHash` of the customer who filled in the form in one of the following ways: - If Synerise SDK is initialized, use the following function: ``` SR.client.hashIdentity("unique_id") ``` where `unique_id` is the email or custom ID - If Synerise SDK is not initialized, use the following JS code or your own version of it, which can be written in another language:
// arguments
      // data: string (email or customId) to create hash from

      // returned value
      // hash: hashed string

      hashString: function (data) {
          var hash = 0;
          if (data.length === 0) {
              return hash;
          }
          for (var i = 0; i < data.length; i++) {
              var char = data.charCodeAt(i);
              hash = ((hash << 5) - hash) + char;
              hash = hash & hash;
          }
          return hash;
      }
1. Compare the generated hash with `identityHash` from the `_snrs_p` cookie: - [`identityHash` is identical](#if-identityhash-is-identical) - [`identityHash` is not identical](#if-identityhash-is-not-identical) #### If identityHash is identical The customer who filled the form is the same as the one who visited the site previously. You can send their data. 1. Send a `form.submit` event. The data from the form is stored in the `params` object. API reference is available [here](https://hub.synerise.com/api-reference/data-management#operation/CustomEvent).
See curl example (email)
curl --location --request POST 'https://{SYNERISE_API_BASE_PATH}/v4/events/custom' \ --header 'Authorization: Bearer eyJh...T-hyeIc' \ --header 'Api-Version: 4.4' \ --header 'Content-Type: application/json' \ --data-raw '{ "label": "Customer submitted a form", "action": "form.submit", "client": { "email": "example@synerise.com" }, "params": { "firstname": "John", "lastname": "Doe", "formType": "exampleFormType" } }'
See curl example (customId)
curl --location --request POST 'https://{SYNERISE_API_BASE_PATH}/v4/events/custom' \ --header 'Authorization: Bearer eyJh...T-hyeIc' \ --header 'Api-Version: 4.4' \ --header 'Content-Type: application/json' \ --data-raw '{ "label": "Customer submitted a form", "action": "form.submit", "client": { "customId": "example@synerise.com" }, "params": { "firstname": "John", "lastname": "Doe", "formType": "exampleFormType" } }'
**Result:** The data from the form is saved to the customer's account. #### If identityHash is not identical The customer who filled the form is not the same who visited the site previously. 1. Generate an UUIDv5 for the customer. For details, see [this article](/developers/web/uuids#generating-uuidv5). 2. Send a create/update API call to create/update the profile which is the new context with the UUIDv5. The request body is a single-object array. The object contains the new UUIDv5 and the unique identifier. If the profile already has this UUIDv5, sending the same data again does not cause any problems. You do not need to check before sending the call. API reference is available [here](https://hub.synerise.com/api-referenceClientManagement/ClientManagement.html#operation/BatchAddOrUpdateClients).
See curl example (email)

The highlighted properties are required, the others are optional. For a comprehensive list of properties you can send, see API reference.

curl --location --request POST '{SYNERISE_API_BASE_PATH}/v4/clients/batch' \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'Api-Version: 4.4' \ --header 'Authorization: Bearer eyJ...yeIc' \ --data-raw '[ { "email": "example@synerise.com", "uuid": "4f82f7a9-0745-55a3-b028-e301b19bf8ec", "agreements": { "email": true, "sms": true }, "tags": [ "exampleTag" ], "attributes": { "customAttribute1": true, "customAttribute2": "string", "customAttribute3": 42 } } ]'
See curl example (customId)

The highlighted properties are required, the others are optional. For a comprehensive list of properties you can send, see API reference.

curl --location --request POST '{SYNERISE_API_BASE_PATH}/v4/clients/batch' \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'Api-Version: 4.4' \ --header 'Authorization: Bearer eyJ...yeIc' \ --data-raw '[ { "customId": "example.customId", "uuid": "d2bdec3a-96d9-5805-9ca2-1557aec691b1", "agreements": { "email": true, "sms": true }, "tags": [ "exampleTag" ], "attributes": { "customAttribute1": true, "customAttribute2": "string", "customAttribute3": 42 } } ]'
**Result:** The profile is created/updated with the new UUIDv5 and the additional data you sent. The UUIDv5 is always the same for a given customer, regardless of where and how it was generated. 1. Send a `form.submit` event. The data from the form is stored in the `params` object. API reference is available [here](https://hub.synerise.com/api-reference/data-management#operation/CustomEvent).
See curl example (email)
curl --location --request POST 'https://{SYNERISE_API_BASE_PATH}/v4/events/custom' \ --header 'Authorization: Bearer eyJh...T-hyeIc' \ --header 'Api-Version: 4.4' \ --header 'Content-Type: application/json' \ --data-raw '{ "label": "Customer submitted a form", "action": "form.submit", "client": { "email": "example@synerise.com" }, "params": { "firstname": "John", "lastname": "Doe", "formType": "exampleFormType" } }'
See curl example (customId)
curl --location --request POST 'https://{SYNERISE_API_BASE_PATH}/v4/events/custom' \ --header 'Authorization: Bearer eyJh...T-hyeIc' \ --header 'Api-Version: 4.4' \ --header 'Content-Type: application/json' \ --data-raw '{ "label": "Customer submitted a form", "action": "form.submit", "client": { "customId": "example@synerise.com" }, "params": { "firstname": "John", "lastname": "Doe", "formType": "exampleFormType" } }'
4. Store the new UUIDv5 in the browser in one of the following ways: - If after SDK initialization: use the `SR.client.setUuid("new_uuid");` method; replace `new_uuid` with the UUID. The UUID is written to the `_snrs_p` cookie immediately. - If the Synerise SDK is not initialized, store the UUID in the `_snrs_reset_uuid` cookie. The UUID is written to the `_snrs_p` at SDK initialization. **Result:** The customer context in the browser changes to the customer with the new UUIDv5. ## Marketing agreements See [Newsletter agreements](/developers/web/newsletter-agreements). # Web ## Synerise for Web This section explains how to use Synerise with your website. # OG Tags ## Open Graph tags Open Graph tags (OG tags) can be used to additional information about items. When a page visit event is sent, the data from the OG tags is included in the data of that event. You can use this information, for example, to add an item or category context when creating recommendation filters. The name of the property is defined in the `property` attribute, and the value in the `content` attribute. Example:
<!-- "product" is the mandatory og:type for use with dynamic products catalog -->
<meta property="og:type" content="product">

<!-- the mandatory unique product ID, the Stock Keeping Unit (SKU), must be the same as the one sent to the cart/basket -->
<meta property="product:retailer_part_no" content="112233">

<!-- a product's photo -->
<meta property="og:image" content="https://example.com/photo/product_image.jpg">

<meta property="og:title" content="product_name">
<meta property="og:site_name" content="Example Site">
<meta property="og:url" content="https://example.com/product_site.html">

<!-- multiple categories are allowed -->
<meta property="product:category" content="category1_name">
<meta property="product:category" content="category2_name">

<meta property="product:price:amount" content="1,000.00">
<meta property="product:sale_price:amount" content="800.00" />
<meta property="product:original_price:amount" content="1,000.00">
og:tags are included in the URL of the SDK request. If there are too many, the browser may not process the request. The following table presents the URL length limits for different browsers: | Browser | Maximum URL length | | --- | --- | | Google Chrome | 32779 | | Google Android | 8192 | | Firefox | >64k | | Apple Safari | >64k | | Microsoft Internet Explorer 11| 2047 | | Microsoft Edge 16 | 2047 |
You can add custom information that you want to keep in the catalog:
<meta property="product:customName1" content="customValue1">
<meta property="product:customName2" content="customValue1">
<meta property="product:customName3" content="customValue1">
Using the [inserts](/developers/inserts) mechanism, you can refer to a catalog and retrieve all information contained in it. You can find out more about og:tags on the [Open Graph](http://ogp.me/) website. ### Adding OG tags to a website The OG tags (and other metadata) can be added to the website: - with the [Synerise tracking code](/developers/web/installation-and-configuration#customizing-metadata). - as a static part of the site when you build it. - with your own scripts that modify the page source. The script must run before loading the Synerise SDK. ### OG tags in regular websites A `page.visit` event is sent automatically every time a page is opened/refreshed.
og:tags must be implemented in the structure of the HTML document in the head section of a product card. Tags must be placed at the very beginning of the page, so that they load before the Synerise SDK tracker loads.
### OG tags in single-page applications If your page is a single-page application, the SDK is initialized only once. This means that `page.visit` events must be sent on-demand by your implementation. The way the event must be sent depends on how you implement OG tags in the page: - [OG tags are injected into the source of the page and available for retrieval with JS.](#single-page-with-og-tags) - [OG tags are not available and must be explicitly included in the `page.visit` event.](#single-page-without-og-tags) #### Single-page with OG tags If you inject the OG tags into the source of the page, they will be read and sent to Synerise when you call the following method:
SR.event.pageVisit()
No additional parameters are needed. #### Single-page without OG tags If the OG tags are not included in the source of the page, you must send them as an additional `ogTags`attribute of the `page.visit` event. The attribute is a stringified JSON object. The following example sends five OG tags with the `page.visit` event.
SR.event.pageVisit({
    "ogTags": JSON.stringify({
        "og:type": "product",
        "product:retailer_part_no": "87247894536",
        "og:site_name": "shoeStore",
        "og:title": "Red Sneakers LUE42",
        "product:color": "Red"
    })
})
### OG tag catalog Tags from page.visit events are automatically saved to a catalog named `Snrs-produktu-ogTag`. You can use this catalog to: - Verify that data from a page.visit event was sent correctly to Synerise (if it wasn't, it's not in the catalog) - Use data from this catalog in inserts. In this case, remember that the data is only updated when the item page is opened - so if an item wasn't viewed for a long time, the data in the catalog may be out-of-date. # Transactions and basket events Tracking transactions lets you use features such as eCommerce analytics, product purchase segmentation, or cart/transaction based automations. ## Authentication Requests to the SDK may require customer authentication. For more details, see [this article](/developers/web/jwt-auth). ## Using Google Data Layer If you use [Google Analytics 4 e-commerce](https://developers.google.com/analytics/devguides/collection/ga4/ecommerce), you can send data to it when using Synerise event tracking.
If you created the tracking code with the [generator](/developers/web/installation-and-configuration#creating-a-tracking-code), you don't need to edit it.
If your tracking code was created without the generator, add the `dataLayer` and `gaVersion` properties to `SR.init()`:
SR.init({
    "trackerKey":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "dataLayer": dataLayer,
    "gaVersion": "CHOOSE_VERSION"
});
The `gaVersion` parameter is used to set the Google Analytics implementation. You can only choose one implementation for use with Synerise tracking. - To send events to Google Analytics 4 Tag Manager implementation, set the value to `GA_4` - To send events to Google Analytics 4 gtag.js implementation, set the value to `GA_4_TAG` When you send events to Google Data Layer, some item parameters are saved in Synerise under different names than in the Data Layer request: | Parameter name in Data Layer | Parameter name in Synerise | | ---------------------------- | -------------------------------------------------------------------- | | `item_category` | `$categories` (array) | | `item_id` | `$sku` | | `price` | `$finalUnitPrice` | | `item_name` | `$title` | | `quantity` | `$quantity` | | `value`/`revenue` | `$totalAmount` | | `transaction_id` | `orderId` | | `item_*` | `item_` is removed, for example `item_variant` is saved as `variant` | Other parameters are saved without changing their names. ### Product added to shopping cart This call creates a [`product.addToCart` event](/docs/assets/events/event-reference/items#productaddtocart).
dataLayer.push({
  event: "add_to_cart",
  ecommerce: {
    currency: "USD",
    value: 7.77,
    items: [
    {
      item_id: "SKU_12345",
      item_name: "Stan and Friends Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 2.22,
      index: 0,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "green",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 9.99,
      quantity: 1
    }
    ]
  }
});
gtag("event", "add_to_cart", {
  currency: "USD",
  value: 7.77,
  items: [
    {
      item_id: "SKU_12345",
      item_name: "Stan and Friends Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 2.22,
      index: 0,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "green",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 9.99,
      quantity: 1
    }
  ]
});
### Product removed from shopping cart This call creates a [`product.removeFromCart` event](/docs/assets/events/event-reference/items#productremovefromcart).
dataLayer.push({
  event: "remove_from_cart",
  ecommerce: {
    currency: "USD",
    value: 7.77,
    items: [
    {
      item_id: "SKU_12345",
      item_name: "Stan and Friends Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 2.22,
      index: 0,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "green",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 9.99,
      quantity: 1
    }
    ]
  }
});
gtag("event", "remove_from_cart", {
  currency: "USD",
  value: 7.77,
  items: [
    {
      item_id: "SKU_12345",
      item_name: "Stan and Friends Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 2.22,
      index: 0,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "green",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 9.99,
      quantity: 1
    }
  ]
});
### Purchase details This call creates a [`transaction.charge` event](/docs/assets/events/event-reference/items#transactioncharge) and corresponding [`product.buy` events](/docs/assets/events/event-reference/items#productbuy).
dataLayer.push({
  event: "purchase",
  ecommerce: {
      transaction_id: "T_12345",
      value: 25.42,
      tax: 4.90,
      shipping: 5.99,
      currency: "USD",
      coupon: "SUMMER_SALE",
      items: [
       {
        item_id: "SKU_12345",
        item_name: "Stan and Friends Tee",
        affiliation: "Google Merchandise Store",
        coupon: "SUMMER_FUN",
        discount: 2.22,
        index: 0,
        item_brand: "Google",
        item_category: "Apparel",
        item_category2: "Adult",
        item_category3: "Shirts",
        item_category4: "Crew",
        item_category5: "Short sleeve",
        item_list_id: "related_products",
        item_list_name: "Related Products",
        item_variant: "green",
        location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
        price: 9.99,
        quantity: 1
      },
      {
        item_id: "SKU_12346",
        item_name: "Google Grey Women's Tee",
        affiliation: "Google Merchandise Store",
        coupon: "SUMMER_FUN",
        discount: 3.33,
        index: 1,
        item_brand: "Google",
        item_category: "Apparel",
        item_category2: "Adult",
        item_category3: "Shirts",
        item_category4: "Crew",
        item_category5: "Short sleeve",
        item_list_id: "related_products",
        item_list_name: "Related Products",
        item_variant: "gray",
        location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
        price: 20.99,
        promotion_id: "P_12345",
        promotion_name: "Summer Sale",
        quantity: 1
      }]
  }
});
gtag("event", "purchase", {
    transaction_id: "T_12345",
    value: 25.42,
    tax: 4.90,
    shipping: 5.99,
    currency: "USD",
    coupon: "SUMMER_SALE",
    items: [
     {
      item_id: "SKU_12345",
      item_name: "Stan and Friends Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 2.22,
      index: 0,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "green",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 9.99,
      quantity: 1
    },
    {
      item_id: "SKU_12346",
      item_name: "Google Grey Women's Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 3.33,
      index: 1,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "gray",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 20.99,
      promotion_id: "P_12345",
      promotion_name: "Summer Sale",
      quantity: 1
    }]
});
## Tracking transactions without Google Data Layer If you're not integrated with Google Data Layer, you can create your own array variable and connect it to Synerise using the SDK:
SR.init({
    "trackerKey":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "dataLayer": window["syneriseLayer"] = []
});
After this configuration, you can send objects like the ones above to the `syneriseLayer` variable instead of the `dataLayer` variable:
syneriseLayer.push({...})
# Tracking form data You can use forms in different contexts. Each form can send data to Synerise, using additional parameters that do not other uses of the form. # Newsletter agreements You can enable newsletter agreements by using an HTML form or calling the SDK. For the API method, see [Managing newsletter agreements with API](/developers/api/clients/newsletter-agreements).
Custom agreements, such as agreement to receive alcohol commercials, are saved as custom profile attributes (for example, `"agreeToAlcoholAds": true`). They can be managed like other custom attributes.
If you want to collect custom attributes for use as agreements with an HTML form or JS SDK methods, see [Tracking form data](/developers/web/tracking-form-data).
## Prerequisites These prerequisites apply to HTML forms and SDK methods. - Ensure that a [workflow for collecting newsletter agreements](/docs/settings/configuration/newsletter-sign-up) is running. - If you're not authenticating the form with [JWT](/developers/web/jwt-auth), ensure that the `form.submit` event is allowed to: - be sent without JWT. - update profile information without JWT. See [Event authentication settings](/docs/assets/events/event-settings). ## HTML form Use the `data-synerise="newsletterAgreement"` and `data-synerise-value="enabled"` attributes (both attributes are required) on an `input` element in the form.
Option 1: Invisible input element; customer only provides the email
<form action="" method="post" data-synerise="newsletter"> <input type="text" name="email" data-synerise="email" placeholder="Email" value="john.doe@synerise.com" /> <input type="submit" value="Subscribe"> <input type="hidden" data-synerise="newsletterAgreement" data-synerise-value="enabled" id="newsletterAgreement"> <!-- Additional fields --> </form>
Option 2: A visible checkbox

The value and additional attributes of the checkbox are sent only if the checkbox is selected.

<form action="" method="post" data-synerise="newsletter"> <input type="text" name="email" data-synerise="email" placeholder="Email" value="john.doe@synerise.com" /> <input type="checkbox" data-synerise="newsletterAgreement" data-synerise-value="enabled" id="newsletterAgreement" checked> <label for="newsletterAgreement">I want to receive the newsletter</label> <input type="submit" value="Subscribe"> <!-- Additional fields --> </form>
This information is processed in the following way: 1. A `form.submit` event with the data is saved to the customer's account. 2. The customer's profile is updated with the `'newsletter_agreement_enabled': 'enabled'` attribute. 3. An event with details of the profile update is created and triggers the [workflow that collects newsletter agreements](/docs/settings/configuration/newsletter-sign-up). 4. One of the following happens: - If single opt-in is used, the agreement is enabled. Depending on the workflow configuration, the customer may receive an email with a notification. - If double opt-in is used, the customer receives an email and must click the link in that email to confirm the subscription. ## JavaScript SDK ### Enabling a newsletter agreement To enable a customer's newsletter agreement, use the `SR.event.sendFormData()` method. As the profile identifier, you can use the email or the custom ID:
Email can be used as an identifier only when [non-unique emails](/docs/settings/configuration/non-unique-emails) are disabled.
SR.event.sendFormData('newsletter-agreement', {
    email: 'john.doe@synerise.com',
    newsletterAgreement: 'enabled' //translates to "newsletter_agreement_enabled: 'enabled'" for the backend
})
Custom ID can be used as an identifier only when [non-unique emails](/docs/settings/configuration/non-unique-emails) are enabled.
SR.event.sendFormData('newsletter-agreement', {
    custom_identify: 'somecustomid',
    newsletterAgreement: 'enabled' //translates to "newsletter_agreement_enabled: 'enabled'" for the backend
})
This information is processed in the following way: 1. A `form.submit` event with the data is saved to the customer's account. 2. The customer's profile is updated with the `'newsletter_agreement_enabled': 'enabled'` attribute. 3. An event with details of the profile update is created and triggers the [workflow that collects newsletter agreements](/docs/settings/configuration/newsletter-sign-up). 4. One of the following happens: - If single opt-in is used, the agreement is enabled. Depending on the workflow configuration, the customer may receive an email with a notification. - If double opt-in is used, the customer receives an email and must click the link in that email to confirm the subscription. ### Disabling a newsletter agreement To disable a customer's newsletter agreement, use the `SR.event.sendFormData()` method. As the profile identifier, you can use the email address or the custom ID:
Email can be used as an identifier only when [non-unique emails](/docs/settings/configuration/non-unique-emails) are disabled.
SR.event.sendFormData('newsletter-agreement', {
    email: 'john.doe@synerise.com',
    newsletterAgreement: 'disabled'
})
Custom ID can be used as an identifier only when [non-unique emails](/docs/settings/configuration/non-unique-emails) are enabled.
SR.event.sendFormData('newsletter-agreement', {
    custom_identify: 'somecustomid',
    newsletterAgreement: 'disabled'
})
The agreement is disabled immediately and a `form.submit` event with the data is saved to the customer's account. # Authenticating requests with JSON Web Tokens (JWT) [JSON Web Tokens (JWT)](https://jwt.io/) can be used to authenticate JS SDK requests from recognized customers. This provides a way to identify customers before authorizing requests that modify personal data.
See implementation of event authorization with JWT in [Event authorization in JS SDK with Flask](/use-cases/anonymous-profile-to-recognized).
By default, the `form.submit` events require JWT authentication. If you want to enable this for other events, see [Event authentication settings](/docs/assets/events/event-settings). The tokens are generated by your backend. Synerise requires a JWT encoded with the RS256 algorithm (this is **not** the default algorithm used by the [jwt.io debugger](https://jwt.io/)).
JWTs created for use with Web SDK can't be used to authenticate API requests. This is a different type of authentication.
## Prerequisites: A public RSA key must be added to Synerise.
If keys were not added before, expand and follow the procedure before you continue
  1. Go to Data Modeling Hub icon Data Modeling Hub > Events.

  2. On the JS SDK event settings tab, in the Certificate section, click Define.

  3. If a certificate is already added, perform one of the following actions

    • Keep using the existing certificate, no further actions are required.
    • Overwrite the existing certificate by continuing to step 4.

    Overwriting a certificate requires providing the new certificate in your backend implementation! JWT tokens signed with the old certificate are rejected!

  4. Open the terminal.

  5. Generate public and private RSA keys by using these commands:

    1. openssl genpkey -out private.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048
    2. openssl pkcs8 -topk8 -inform pem -in private.pem -outform DER -nocrypt -out private.der
    3. openssl rsa -pubout < private.pem > public.pem
  6. Perform one of the following actions:

    • To enter the certificate as text, in the Certificate code field paste the certificate with the header and footer.
      The header and footer are: -----BEGIN PUBLIC KEY-----; -----END PUBLIC KEY-----

    The pasted certificate cannot contain line breaks or spaces.

    To open the certificate in the terminal, you can usually use cat public.pem in the root directory.

    • To upload the certificate as a file, click Upload Certificate > Upload certificate code and select a file from your computer.
  7. Click Apply.

## Implementation overview This flowchart is a high-level overview of the JWT creation logic. Your implementation must cover all of these scenarios. The details are described in [this section](#implementation-details).
Diagram that shows the logic of JWT authentication
Overview of JWT implementation logic
## Implementation details When a customer provides their email (for example, when logging in), generate a JWT for the customer. The provided email is used as `customer_email` everywhere in this process. ### Check if identity hash exists 1. Initialize the JS SDK. 1. Check the current identity hash by calling the `SR.client.getIdentityHash()` method. 2. Depending on the result, continue to one of these procedures: 1. If the method returns an empty string, the hash does not exist. Follow [this instruction](#if-an-identity-hash-does-not-exist). 2. If the method returns a non-empty string, a hash exists. Follow [this instruction](#if-an-identity-hash-exists). ### If an identity hash does NOT exist 1. Generate an identity hash by calling the `SR.client.hashIdentity("customer_email")` method. 2. From the `_snrs_uuid` cookie, retrieve the customer's UUID. 3. Generate a JWT. In the payload, provide the `customer_email` and the UUID retrieved from the cookie. For details, see [this section](#generating-json-web-tokens-jwt). 4. Call the `SR.client.setUuidAndIdentityHash("email_hash", "customer_uuid")` method, where: - `email_hash` is the hash you generated earlier with `SR.client.hashIdentity("customer_email")` - `customer_uuid` is the customer UUID retrieved from the `_snrs_uuid` cookie and encoded in the JWT **Result:** The customer can now send events that require JWT authentication. ### If an identity hash exists 1. Call the `SR.client.getIdentityHash()` method. 2. Call the `SR.client.hashIdentity("customer_email")` method. 3. Compare the returned values. - If the values are identical, the identity matches the current customer. Follow this [this instruction](#if-the-identity-matches-the-current-customer). - If the values are different, the identity does not match the current customer. Follow this [this instruction](#if-the-identity-does-not-match-the-current-customer). #### If the identity matches the current customer 1. From the `_snrs_uuid` cookie, retrieve the customer's UUID. 3. Generate a JWT. In the payload, provide the `customer_email` and the UUID retrieved from the cookie. For details, see [this section](#generating-json-web-tokens-jwt). **Result:** The customer can now send events that require JWT authentication. #### If the identity does not match the current customer: 1. Generate a new UUIDv5 using the `customer_email`. For details, see [this section](/developers/web/uuids#generating-uuidv5). 2. Generate an identity hash by calling the `SR.client.hashIdentity("customer_email")` method. 3. Generate a JWT. In the payload, provide the `customer_email` and the UUID you generated. For details, see [this section](#generating-json-web-tokens-jwt). 4. Call the `SR.client.setUuidAndIdentityHash("email_hash", "customer_uuid")` method, where: - `email_hash` is the hash you generated earlier with `SR.client.hashIdentity("customer_email")` - `customer_uuid` is the customer UUID retrieved from the `_snrs_uuid` cookie and encoded in the JWT **Result:** The customer can now send events that require JWT authentication. ### Generating JSON Web Tokens (JWT)
For details on how to implement token creation and encoding, refer to the documentation of the language or framework you are using.
1. In the header, include the following data:
{
   "alg": "RS256”,
   "typ": "JWT"
   }
2. In the payload, include the following data:
{
   "exp": 1599737564, // expiry time as a UNIX timestamp, less than 7 days away
   "uuid": "af0a5e16-dc1f-5242-8b22-daf62c3cb78d", // customer's UUID
   "email": "customer.email@domain.com" // customer's email
   }
The token lifetime cannot be longer than 7 days.
1. Sign the token with the public and private keys. 2. Encode the token. 2. Apply the encoded token in one of the following ways: - Store the token in the `_snrs_token` cookie. - Call the `SR.client.setAccessToken("token-as-a-string")` [JS SDK method](/developers/web/methods-reference#authentication-by-json-web-token-jwt). **Result:** The JWT is stored as `snr-token` in local storage. If you applied the token by using a cookie, the cookie is deleted. **You may want to return to:** - [The identity hash does not exist](#if-an-identity-hash-does-not-exist) - [The identity hash matched the current customer](#if-the-identity-matches-the-current-customer) - [The identity hash did not match the current customer](#if-the-identity-does-not-match-the-current-customer) # Customer UUIDs The actions described in this article are usually only performed when procedures from other articles require them. ## Generating UUIDv5 UUIDv5 is generated by providing a namespace and an identifier string. When working with Synerise, the identifier string is a concatenation of a salt string (identical for all of your customers, everywhere on the site) and an identifier. **The resulting UUID is always the same for a given `salt+identifier` combination.** Thanks to this, you can always assign the same UUID to a customer, regardless of where the UUID was generated.
- The salt can be any string. - By default, the customer's unique identifier is email. You can configure Synerise to use [custom ID](/docs/settings/configuration/non-unique-emails) instead.
The following example shows how to generate a UUIDv5 in Python 3.8:
import uuid

salt = "someString" # identical for the entire site
uniqueIdentifier = "customer@synerise.com" # email (default) or customId
generatedUuid = uuid.uuid5(uuid.NAMESPACE_URL, (salt + uniqueIdentifier))
The result of running the above code example is always `345d4c8f-5aff-591d-a19c-1ca48923d9ee`. Synerise does not the decode the UUID and cannot re-construct the data the token was created from. For more instructions on how to generate a UUIDv5, refer to the documentation of the language or framework you are using. ## Resetting customer UUIDs You can reset the UUID of a customer to a value provided by your application. This can be used, for example, to separate the activities of several customers who share a device. You can do this with: - [a cookie](#with-cookie) - [a query parameter](#with-query-parameter) - [an SDK method](#with-sdk-method)
The UUID [should not be completely random](#generating-uuidv5). However, a fully random UUIDv4 is also allowed, depending on your integration and requirements.
### With cookie **Before initializing the SDK**, store the new UUID in a `_snrs_reset_uuid` cookie. When the page is refreshed/SDK is initialized, the SDK detects the cookie, saves the new UUID to the `_snrs_uuid` cookie, and deletes the `_snrs_reset_uuid` cookie. ### With query parameter You can add an `snrs_reset_uuid=NEW_UUID` query parameter to a link to force setting an UUID. The new UUID is saved in the `_snrs_uuid` cookie. This setting works independently from the [Managing user context feature](/docs/settings/configuration/non-unique-emails#managing-user-context). **Example**
https://site.example.com/?snrs_reset_uuid=a6663a59-9d16-5093-bd27-84a829d001eb
### With SDK method Use the `SR.client.setUuid("new_uuid")` method:
SR.client.setUuid("a6663a59-9d16-5093-bd27-84a829d001eb");
The new UUID is saved in the `_snrs_uuid` cookie. ## How to recognize a UUIDv5? The first digit of the third group in a UUIDv5 is `5`. In a UUIDv4, that digit is `4`.
xxxxxxxx-xxxx-5xxx-xxxx-xxxxxxxxxxxx // UUIDv5
xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx // UUIDv4
# Tracking cart status This article presents one of the methods of tracking cart contents in a web environment. While tracking the contents of a cart on a website, you may run into issues with session time or tracking events that add/remove items. To resolve this, you can retrieve and send custom events that include all the current contents of the cart. An example usage of the cart status events is sending reminders to customers who leave their carts without completing a purchase and sending each update of the cart status to Synerise.
The events described here **do not** modify the cart. Their purpose is only to track the cart's current content for use in marketing scenarios, automations, and analytics.
## Authentication Requests to the SDK may require customer authentication. For more details, see [this article](/developers/web/jwt-auth). ## Updating cart status You must send `cart.status` immediately after the contents of the cart are modified. Example of a custom event that updates the status of a cart:
SR.event.trackCustomEvent('cart.status', {
    products: [
        {
        sku: '236',
        quantity: 2,
        brand: 'brand1',
        category: 'cat1'
        },
        {
        sku: '436',
        quantity: 1,
        brand: 'brand1',
        category: 'cat1'
        }
    ],
    totalAmount: 150,
    totalQuantity: 3,
    itemIds: ["236","436"]
    }, 
'CartStatus');
This custom event contains complete information about a cart - if you want to add an item, you must also include the items that were in the cart before.
### Parameters | Name | Type | Mandatory | Description | | --- | --- | --- | --- | | `products` | array | yes | An array of items in the cart. Cannot contain duplicates. | | `sku` | string | yes | The SKU of the item. Must be the same as the `product:retailer_part_no` value in OG tags and `` or `g:item_group_id` in the product feed. | | `quantity` | float | yes | The quantity of the item in the cart | | `brand` | string | no | The brand of the item | | `category` | string/array | no | A category (string) or categories (array of strings) that the item belongs to. Must be the same as the `og:category` in OG tags and `` in the product feed. | | `totalAmount` | float | no | The total value of the cart | | `totalQuantity` | float | no | The total quantity of items in the cart | | `itemIds`| array | recommended | This is a parameter that stores item IDs from the cart. Thanks to this parameter, you don't need to extract `sku` values from the `products` array to to create analytics based on item IDs; create recommendations; or exclude items from a recommendation if they're already in the cart. | ## Clearing a cart When all the contents of a cart are removed, send a status event with an empty cart. This must be done when a transaction is completed.
SR.event.trackCustomEvent('cart.status', {
products: [],
totalAmount: 0,
totalQuantity: 0
}, 'CartStatus');
# Custom tracking domain Some browsers use mechanisms that disable third-party tracking scripts. This disables Synerise tracking. To avoid this, you can serve the Synerise tracking tools from your own subdomain. When you complete the instructions in this article, the tracking domain will change from a Synerise domain to your sub-domain. Third-party tracking blockers will not affect Synerise tracking. The process involves: 1. [Preparing the domain](#preparing-the-domain). 2. [Creating a tracking code](#creating-a-tracking-code). 3. [Updating Synerise API requests made from the site](#updating-your-synerise-api-requests).
If you're changing to a custom domain in a workspace where Dynamic Content is used to inject Synerise API requests into the website, you will need to update the Dynamic Content too.
## Preparing the domain 1. In your hosting, create a subdomain for Synerise tracking, for example `api.example.com`
The domain name should **NOT**: contain indications that it is used for tracking; refer to Synerise; or include strings typical to Synerise elements, such as `synerise`, `snr`, or `snrs`.
2. Configure a CNAME DNS entry for the created subdomain:
// For Azure Cloud deployments:
   NAME                    TYPE   VALUE
   --------------------------------------------------
   api.example.com.        CNAME  web.snrbox.com.

   // For Azure Cloud USA deployments:
   NAME                    TYPE   VALUE
   --------------------------------------------------
   api.example.com.        CNAME  web.azu.snrbox.com

   // For Google Cloud Platform deployments (currently only available in Belgium):
   NAME                    TYPE   VALUE
   --------------------------------------------------
   api.example.com.        CNAME  web.geb.snrbox.com.
After creating a DNS entry, you may need to wait 24-72 hours before it becomes active.
1. **If you want to use your own certificate**:1. Prepare an X.509-format certificate. 2. Deliver the following files to Synerise Support: - private key (`key.pem`) - Fullchain certificate (`fullchain.pem`): - The leaf certificate **must be the first** in the file. - Intermediate certificates must follow, from the lowest-level to the highest. - **Do not** include the root CA.
- When you use your own certificate, it is your responsibility to monitor its expiration time and re-generate it. - Ensure that the `fullchain.pem` file is complete. Missing certificates or wrong certificate order may cause SSL/TLS errors.
2. **If you want Synerise Support to provide a certificate for you**: 1. Contact Synerise Support to request the certificate. Synerise Support generates a certificate by using third-party solutions such as letsencrypt.org. 1. If your domain has CAA records, add the following record to the root domain or subdomains used with Synerise: ``` api.example.com. IN CAA 0 issue “letsencrypt.org” ```
If your domain does not use CAA records, **you do not have to add them**.
## Creating a tracking code Create a tracking code (or update an existing one) with your custom domain as described in [Getting started](/developers/web/installation-and-configuration) and add it to your website.
Insert the tracking code directly into the code of your website.
Don't use Google Tag Manager for this, because GTM can be treated as third-party and blocked.
## Updating your Synerise API requests In Synerise API requests authorized with the tracker key (for example, [Recommendations](https://hub.synerise.com/api-reference/ai-recommendations#tag/Recommendations), [Search](https://hub.synerise.com/api-reference/ai-search#tag/Search), [AI events](https://hub.synerise.com/api-reference/data-management#tag/AI-Events) APIs), you must: 1. Change the domain to your custom domain. 2. Add `ai/` to the beginning of the endpoint path.
API calls inserted into the page with Dynamic Content must be updated in the same way.
These endpoints can be recognized by the availability of authorization methods other than JWT: - the `X-Api-Key` header (legacy). - the `token` parameter in the query, for example: ``` api.synerise.com/search/v2/indices/123/query?query=q&token=B264B70A-1111-1111-1111-AC35EEFA0B59 |------ tracker key authentication ------| ```
Workspace JWT authorization is available for these endpoints, but should only be used for server-to-server communication.
**Example**: If you make requests to the following endpoint: ```plaintext https://api.synerise.com/search/v2/indices/123/query?query=q&token=B264B70A-1111-1111-1111-AC35EEFA0B59 ``` the new query is:
https://api.example.com/ai/search/v2/indices/123/query?query=q&token=B264B70A-1111-1111-1111-AC35EEFA0B59
# "Do Not Track" mechanism Privacy protection regulations may require that you let the visitors on your website decide that they don't want their activity history to be tracked and associated with their browser or device and let the mobile app users decide that they don't want their activity history to be tracked in the application. In Synerise, you can do this by: - [creating a cookie](#enabling-do-not-track) that tells our SDK to stop tracking visitor activity, but you can still serve campaign content to those visitors (variant of the do not track feature for web SDK) - enabling the do not track method that tells our SDK to stop tracking mobile app user activity (variant of the do not track feature for mobile SDK). ## Main assumptions ### Web If the do-not-track cookie exists: - With each page refresh, the Web SDK generates a random UUID. This UUID isn't saved in the database or associated with a profile. It's only need for Dynamic Content requests.
Don't use the random UUID as a profile identifier in API requests!
- No Synerise cookies are created. - Dynamic Content is only displayed if: - the audience is set to "everyone" - Jinjava inserts in the content don't require a profile context - Only Dynamic Content with the audience set to "everyone" is displayed. - Using SDK methods doesn't generate any events. - The SDK doesn't automatically generate any tracking events (such as `page.visit`). - If the cookie is deleted, tracking is re-enabled after the page is refreshed. In such cases, you should make it possible for a visitor to opt-out again. ### Mobile SDK Tracking is disabled by running the do not track method. If the do not track method is executed, then Synerise mobile SDK works in the following way: - A new random UUID will be generated for the token stored in the mobile app, however a proile isn't created. This may affect the API implementation. In such case, review what API endpoint they use and adjust accordingly (some endpoints may create profile in Synerise, in such case the call should not be performed). - IP and uuid will be available on our access log. - Using SDK methods doesn't generate any events. - The SDK doesn't track any user activity in a mobile app, so the events won't be generated (such as `screen.view`). - If the tracking is re-enabled after the application is reopened, you should make it possible for a mobile app user to opt-out again. ## Impact of Do Not Track on features --- | Feature | Do Not Track enabled | |--------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Client login methods | Red checkmark | | [Web push notifications](/docs/campaign/Webpush) (web) /[Push notifications](/docs/campaign/Mobile) (mobile) | Red checkmark
If the token exists, it will be removed from the profile, which prevents sending notifications; | | [Dynamic content](/docs/campaign/dynamiccontent) (web) / [In-app messages](/docs/campaign/in-app-messages) (mobile) | Green checkmark but:
- Capping won't work,
- ABx testing or control group assignment won't work,
- **[Global control group](/docs/settings/configuration/global-control-group) behavior for dynamic content**: doesn't work; a user with enabled do not track option will be displayed dynamic content only if the content is set to **Everyone** and/or the **Include first visitors** setting is enabled
- **[Global control group](/docs/settings/configuration/global-control-group) behavior for in-app messages**: global control group won't work for users with enabled do not track option
- Interactions with dynamic content and in-app messages are not tracked,
- Jinjava is rendered as for an anonymous profile | | [Documents](/docs/assets/documents) and [screen views](/docs/campaign/screen-views) | Green checkmark but:
- Activities are not tracked (such as generating `screen.view` events),
- Jinjava is rendered as for anonymous profile | | [AI Search](/docs/ai-hub/ai-search) | Green checkmark but:
Search results will be returned as for an anonymous profile | | [Jinjava: catalogs](/developers/inserts/insert-usage#catalogs) | Green checkmark | | [Jinjava: aggregates](/developers/inserts/insert-usage#aggregates) and [expressions](/developers/inserts/insert-usage#expressions) | Red checkmark | | [Jinjava: vouchers](/developers/inserts/insert-usage#code-pools) | Green checkmark but:
- `Assign=false` flag does not work,
- [Event of assigning voucher](/docs/assets/events/event-reference/loyalty#vouchercodeassigned) will not be generated | | [Jinjava: promotions](/developers/inserts/insert-usage#promotions) | Red checkmark | | [Jinjava: recommendations](/developers/inserts/insert-usage#recommendations) | Green checkmark but:
- Recommendations implemented using Jinjava are rendered as for an anonymous profile,
- Interactions with recommendations are not tracked. | ## Enabling Do Not Track ### Web
Before enabling the feature, make sure you know the [main assumptions](#main-assumptions) and [impact on the features](#impact-of-do-not-track-on-features).
1. Decide the cookie name: - If you want to use the default `_snrs_dnt` cookie, go to step 2. - If you want to use a different cookie, add its name to the SDK initialization script, in the `dntCookieName` variable:
SR.init({
          trackerKey: "xxxxxxx",
          dntCookieName: "your_cookie_name"
      });
2. When a visitor rejects the category of cookies where you include Synerise: 1. Create the do-not-track cookie with a value of `1` or `true` 2. Force refreshing the page to enable Do Not Track. **Result**: After the page refreshes, Synerise JS SDK deletes all its cookies and local storage. ### Mobile 1. Make sure that the API key you're using has the `API_PERSONAL_DEVICE_CLIENT_DELETE` permission. To learn about setting permissions, see [API keys](/docs/settings/tool/api#editing-api-keys). 2. Enable Do Not Track feature can be enabled in one of the following ways: - By defining the following parameter to `true` in the settings of the application (this can be defined at any moment):
| Parameter | Type | Default | | --- | --- | --- | | `Synerise.settings.sdk.setDoNotTrack(true)` | `Boolean` | false |
| Parameter | Type | Default | | --- | --- | --- | | `Synerise.settings.sdk.doNotTrack` | `Bool` | false |
- By applying the following method during the initialization of the application; this method lets you set the initial value of the Do Not Track feature to any value (true or false); - This is a one-time setting that is only applied during the first initialization; **not** each time the application starts. - If you need to change this setting later, you can do so by adjusting the parameter mentioned in the previous point. - If the parameter has already been set to false (as described in the previous point), any modifications made using the method during initialization will not impact the Do Not Track status.
`.initialDoNotTrack(true)` in the application [Builder](/developers/mobile-sdk/class-reference/android/lifecycle#synerise-builder)
let config = InitializationConfig()
               config.initialDoNotTrack = true

               Synerise.initialize(apiKey: clientApiKey, baseUrl: syneriseBaseURL, config: config)
# Method reference ## Web SDK methods reference ### Authentication by JSON Web Token (JWT) JS SDK calls can be authenticated with JWT. For more details, read [this article](/developers/web/jwt-auth). #### Retrieve current JWT You can check the current token. If no token is set, the method returns null. After retrieving the token from the SDK, you can decode it to check the expiration time and details of the customer.
SR.jwt.getAccessToken();
#### Set JWT Set a new token when a customer logs in or the old token expires. The method takes one argument: the JWT as a string.
SR.client.setAccessToken('token');
#### Clear JWT To log out a user, clear the token.
SR.jwt.clearAccessToken();
### Tracking customer actions #### Basic method for tracking events For more details, click [here](/developers/web/event-tracking).
SR.event.trackCustomEvent(
    "button.click", // event action name
    { // optional parameters — define your own
        "customParam1": "value1",
        "customParam2": "value2",
        "time": 1556474400000 // if provided, the event is recorded in the past with this timestamp; if omitted, the SDK sets the timestamp automatically
    }
)
#### Re-initialize the tracking code You can use this method to re-initialize a search for the `data-synerise` attributes on a page. This is used, for example, in pop-up windows.
SyneriseTC.initFormCatch()
#### Send a page.visit event You can send a page.visit event. This is used, for example, in single-page applications. By default, the `page.visit` event tracks data such as customer UUID, OG tags of the page (if they exist), browser, etc.
SR.event.pageVisit(
  {
    "key": "value" // optional additional parameters
  }
)
### Managing customer data #### Send form data This method allows you to send data from an HTML form to the SDK. This event is sent automatically when a customer sends a form. For more details, click [here](/developers/web/tracking-form-data).
SR.event.sendFormData('contact',
    { //form data
        "surname": "Doe",
        "name": "John",
        "email": "john.doe@synerise.com",
        "customParam1": "customValue1",
        "customParam2": "customValue2"
    },
    { //field mapping
        "lastname": "surname",
        "firstname": "name",
        "email": "email",
        "customAttribute1": "customParam1",
        "customAttribute2": "customParam2"
    }
)
#### Send form data without a form You can emulate the behavior of a form by calling the SDK directly.
- If you use the non-unique email feature, use `custom_identify` instead of `email`. See [non-unique email feature configuration](/docs/settings/configuration/non-unique-emails). - The SDK does not validate the data. For example, if the customer makes an error in their identifier and sends the form, a new profile with that identifier is created. This may cause the event history of an anonymous customer to be merged into a recognized profile with an error in the identifier, even if the user re-sends the form again with the right identifier. To avoid this, validate the entered data before sending the form.
SR.event.sendFormData('formType', {
    lastname: "Doe",
    firstname: "John",
    email: "john.doe@synerise.com",
    customAttribute: "customAttributeValue" // saved in the `attributes` object of a Profile
    // more attributes and custom attributes
})
You can replace `formType` with another value or a number of comma-separated values (no spaces). These values are saved as `formType` in the event and as tags in the customer's Profile. #### Get IdentityHash Generates and automatically saves `IdentityHash` based on: - `email` (for unique emails), - `custom_identify` (for non-unique emails). This method returns a string.
SR.client.getIdentityHash()
#### Calculate IdentityHash Calculates `IdentityHash` for any string. This method returns a number.
SR.client.hashIdentity('john.doe@synerise.com')
#### Send newsletter agreements You can use this method to send a customer's newsletter agreements. For more details, click [here](/developers/web/newsletter-agreements).
SyneriseTC.sendFormData('newsletter', {
    // depending on the configuration, email (default) or custom_identify is used as the identifier
    email:'john.doe@synerise.com',
    firstname:'John'
    }
)
### Tracking transactions Transactions can be tracked using Google Data Layer or sent to the Synerise tracker, which uses an identical format. #### Send a "product added to cart" event This call creates a [`product.addToCart` event](/docs/assets/events/event-reference/items#productaddtocart).
dataLayer.push({
  event: "add_to_cart",
  ecommerce: {
    currency: "USD",
    value: 7.77,
    items: [
    {
      item_id: "SKU_12345",
      item_name: "Stan and Friends Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 2.22,
      index: 0,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "green",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 9.99,
      quantity: 1
    }
    ]
  }
});
gtag("event", "add_to_cart", {
  currency: "USD",
  value: 7.77,
  items: [
    {
      item_id: "SKU_12345",
      item_name: "Stan and Friends Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 2.22,
      index: 0,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "green",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 9.99,
      quantity: 1
    }
  ]
});
#### Send a "product removed from cart" event This call creates a [`product.removeFromCart` event](/docs/assets/events/event-reference/items#productremovefromcart).
dataLayer.push({
  event: "remove_from_cart",
  ecommerce: {
    currency: "USD",
    value: 7.77,
    items: [
    {
      item_id: "SKU_12345",
      item_name: "Stan and Friends Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 2.22,
      index: 0,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "green",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 9.99,
      quantity: 1
    }
    ]
  }
});
gtag("event", "remove_from_cart", {
  currency: "USD",
  value: 7.77,
  items: [
    {
      item_id: "SKU_12345",
      item_name: "Stan and Friends Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 2.22,
      index: 0,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "green",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 9.99,
      quantity: 1
    }
  ]
});
#### Send purchase details This call creates a [`transaction.charge` event](/docs/assets/events/event-reference/items#transactioncharge) and corresponding [`product.buy` events](/docs/assets/events/event-reference/items#productbuy).
dataLayer.push({
  event: "purchase",
  ecommerce: {
      transaction_id: "T_12345",
      value: 25.42,
      tax: 4.90,
      shipping: 5.99,
      currency: "USD",
      coupon: "SUMMER_SALE",
      items: [
       {
        item_id: "SKU_12345",
        item_name: "Stan and Friends Tee",
        affiliation: "Google Merchandise Store",
        coupon: "SUMMER_FUN",
        discount: 2.22,
        index: 0,
        item_brand: "Google",
        item_category: "Apparel",
        item_category2: "Adult",
        item_category3: "Shirts",
        item_category4: "Crew",
        item_category5: "Short sleeve",
        item_list_id: "related_products",
        item_list_name: "Related Products",
        item_variant: "green",
        location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
        price: 9.99,
        quantity: 1
      },
      {
        item_id: "SKU_12346",
        item_name: "Google Grey Women's Tee",
        affiliation: "Google Merchandise Store",
        coupon: "SUMMER_FUN",
        discount: 3.33,
        index: 1,
        item_brand: "Google",
        item_category: "Apparel",
        item_category2: "Adult",
        item_category3: "Shirts",
        item_category4: "Crew",
        item_category5: "Short sleeve",
        item_list_id: "related_products",
        item_list_name: "Related Products",
        item_variant: "gray",
        location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
        price: 20.99,
        promotion_id: "P_12345",
        promotion_name: "Summer Sale",
        quantity: 1
      }]
  }
});
gtag("event", "purchase", {
    transaction_id: "T_12345",
    value: 25.42,
    tax: 4.90,
    shipping: 5.99,
    currency: "USD",
    coupon: "SUMMER_SALE",
    items: [
     {
      item_id: "SKU_12345",
      item_name: "Stan and Friends Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 2.22,
      index: 0,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "green",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 9.99,
      quantity: 1
    },
    {
      item_id: "SKU_12346",
      item_name: "Google Grey Women's Tee",
      affiliation: "Google Merchandise Store",
      coupon: "SUMMER_FUN",
      discount: 3.33,
      index: 1,
      item_brand: "Google",
      item_category: "Apparel",
      item_category2: "Adult",
      item_category3: "Shirts",
      item_category4: "Crew",
      item_category5: "Short sleeve",
      item_list_id: "related_products",
      item_list_name: "Related Products",
      item_variant: "gray",
      location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
      price: 20.99,
      promotion_id: "P_12345",
      promotion_name: "Summer Sale",
      quantity: 1
    }]
});
#### Enable syneriseLayer transaction tracking You can use this method for transaction tracking if you're not using Google Data Layer.
SR.init({
    "trackerKey":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "dataLayer": window["syneriseLayer"] = []
});
#### Send a transaction to syneriseLayer syneriseLayer queries are formatted in the same way as Google Data Layer queries.
syneriseLayer.push({...})
### Tracking campaign interactions #### Send a "dynamicContent.show" event By default, the `dynamicContent.show` event is tracked automatically when a Dynamic Content campaign is displayed to the visitor. If the the event is not tracked automatically for your campaign, you can send it using the dedicated method below. This lets you build analytics and measure the performance of your communication.
SR.event.dynamicContentShow(
  {
    "id": "value", // campaign ID
    "variantId": "value", // variant ID
    "key": "value" // optional additional parameters
  },
  "Dynamic content was displayed"
)
#### Send a "dynamicContent.click" event The `dynamicContent.click` event is tracked automatically when a link or a button from Dynamic Content campaign is clicked by the Profile. If the the event is not tracked automatically for any link in your campaign, you can send it using the dedicated method below. This lets you build analytics and measure the performance of your communication.
SR.event.dynamicContentClick(
  {
    "id": "value", // campaign ID
    "variantId": "value", // variant ID
    "key": "value" // optional additional parameters
  },
  "Dynamic content was clicked" // Optional label, not saved in persistent storage
)
#### Send a "recommendation.view" event By default, the `recommendation.view` event is tracked automatically when a recommended items are displayed to a visitor within the Dynamic Content campaign. If the the event is not tracked automatically for your campaign, you can send it using the dedicated method below. This lets you build analytics and measure the performance of your communication.
SR.event.recommendationView(
  {
    "campaignId": "value", // ID of the recommendation campaign related to the event
    "correlationId": "value", // correlation ID of the response from recommendation campaign. Its value is included in the links to recommended items
    "items": ["value", "value"], // an array of items included in the recommendation 
    "key": "value" // optional additional parameters
  },
  "Recommended items were displayed" // Optional label, not saved in persistent storage
)
#### Send a "recommendation.click" event By default, the `recommendation.click` event is tracked automatically when a recommended item is clicked by the Profile within the Dynamic Content campaign. If the the event is not tracked automatically for the links to reccommended items in your campaign, you can send it using the dedicated method below. This lets you build analytics and measure the performance of your communication.
SR.event.recommendationClick(
  {
    "campaignId": "value", // ID of the recommendation campaign related to the event
    "correlationId": "value", // correlation ID of the response from recommendation campaign. Its value is included in the links to recommended items
    "item": "value", // ID of the clicked item (also called `sku`, `productId`, and `retailer_part_no`) 
    "key": "value" // optional additional parameters
  },
  "Recommended item was clicked" // Optional label, not saved in persistent storage
)
#### Send a "item.search.click" event You can send the `item.search.click` event using the dedicated method below. The event should be sent when a visitor clicks an item in AI search results. This lets you build analytics and measure the performance of your communication.
SR.event.itemSearchClick(
  {
    "correlationId": "value", // correlation ID of the response from AI search. Its value is included in the links to returned items
    "item": "value", // ID of the clicked item (also called sku, productId, and retailer_part_no) 
    "position": 1, // position of the clicked item in the result list (count starts with 1)
    "searchType": "autocomplete", // type of the search. The value can be "full-text-search", "autocomplete", or "listing"
    "key": "value" // optional additional parameters
  },
  "An item in search results was clicked" // Optional label, not saved in persistent storage
)
### Dynamic content #### Get campaigns rendered on current page You can retrieve the data of campaigns that were rendered on the current page.
SR.dynamicContent.getRendered()
The output is an array of Dynamic Content campaigns that were rendered on the current page. Each object contains metadata of the campaign, such as its UUID, capping, triggers, variants, and so on. The `variant` object stores the HTML, JS, and CSS content of the campaign, with Inserts already processed. #### Get campaign content on demand You can retrieve the content of a single Dynamic Content campaign. The campaign must be active.
SR.dynamicContent.get("campaignUuid")
The command makes an API request to fetch the campaign. The response contains the HTML, JS, and CSS (with inserts already processed) of the campaign in the `variants` array, in the `content` object of a variant. **Example:** Use the following method to retrieve the content of the Dynamic Content campaign that displays the search box on top of this page:
SR.dynamicContent.get("23c47a51-8d63-42c4-8f83-9c5352532732")
# Advanced tracking code settings
We recommend creating and editing tracking codes with the creator, as described in [Getting started](/developers/web/installation-and-configuration).
This article describes the parameters you can find in tracking codes. You may use this information for editing existing tracking codes, especially if your integration was built before the introduction of the tracking code creator in the Synerise Platform. If you need to create a new tracking code and then manually edit its settings, create it as described in [Getting started](/developers/web/installation-and-configuration) and then return to this article. ## Tracking code in Single Page Applications If your website is a Single Page Application (SPA), the tracking code must be modified. The modification changes the mechanism of sending page visit events and retrieving dynamic content. 1. Add the highlighted parameters to the tracking code:
function onSyneriseLoad() {
           SR.init({
               'trackerKey':'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
               'customPageVisit': true,
               'dynamicContent': {
                   'virtualPage': true
               }
           });
       }
**Result:** The additional initialization parameters disable page visit events and dynamic content retrieval. 1. Re-enable page visit tracking and dynamic content retrieval by implementing the following methods in the page:
SR.event.pageVisit()
       .then(function () {
           SR.dynamicContent.get();
   })
Page visits and dynamic content retrieval must be implemented according to the following rules: - og:tags must be loaded first, regardless of the method that is used to load them - page visits and dynamic content must be requested whenever the page is loaded, reloaded, and when the view changes
You can use Google Tag Manager to implement the methods. To do so, trigger `SR.event.pageVisit();` and `SR.dynamicContent.get();` methods on events that indicate a page or DOM being loaded. `SR.init` is only called when DOM is loaded.
## Tracking script variants (no custom domain) Synerise offers several variants of our Javascript SDK that you can use depending on the required features. Fewer features usually result in smaller page size and shorter load times. | Script version | URI | | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | default:
Script with all functionalities | [synerise-javascript-sdk.min.js](https://web.snrbox.com/synerise-javascript-sdk.min.js) | | no-wp:
Script without WebPush | [synerise-javascript-sdk-no-wp.min.js](https://web.snrbox.com/synerise-javascript-sdk-no-wp.min.js) | ## Additional tracking configuration parameters The only required parameter during the initialization of the tracking code is the `trackerKey` parameter. By using the additional parameters described below, you can modify the configuration of the tracking code. ### Google dataLayer If you use [Google Analytics 4 e-commerce](https://developers.google.com/analytics/devguides/collection/ga4/ecommerce), you can send data to it when using Synerise event tracking.
If you created the tracking code with the [generator](/developers/web/installation-and-configuration#creating-a-tracking-code), you don't need to edit it.
If your tracking code was created without the generator, add the `dataLayer` and `gaVersion` properties to `SR.init()`:
SR.init({
    "trackerKey":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "dataLayer": dataLayer,
    "gaVersion": "CHOOSE_VERSION"
});
The `gaVersion` parameter is used to set the Google Analytics implementation. You can only choose one implementation for use with Synerise tracking. - To send events to Google Analytics 4 Tag Manager implementation, set the value to `GA_4` - To send events to Google Analytics 4 gtag.js implementation, set the value to `GA_4_TAG` When you send events to Google Data Layer, some item parameters are saved in Synerise under different names than in the Data Layer request: | Parameter name in Data Layer | Parameter name in Synerise | | ---------------------------- | -------------------------------------------------------------------- | | `item_category` | `$categories` (array) | | `item_id` | `$sku` | | `price` | `$finalUnitPrice` | | `item_name` | `$title` | | `quantity` | `$quantity` | | `value`/`revenue` | `$totalAmount` | | `transaction_id` | `orderId` | | `item_*` | `item_` is removed, for example `item_variant` is saved as `variant` | Other parameters are saved without changing their names. ### Subdomains If you have **several subdomains** with different tracking codes, they generate cookies with their own domains. If you want the sub-domains to create cookies for another domain instead, declare the domain in the subdomains' tracking codes.
The provided domain must be a parent domain of the site with the tracking code.
**Example**: If your site is `docs.example.com`, it would generate cookies with the `docs.example.com` domain. To generate cookies with the root domain, the tracking code needs the following parameter:
SR.init({
    'trackerKey':'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
    'domain':'.example.com'
});
### Automatic tracking of page visits You can turn off the **automatic collection of page visit events** with the `customPageVisit` parameter.
In this case, events should be sent manually using the [SDK methods](/developers/web/event-tracking).
SR.init({
    'trackerKey':'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
    'customPageVisit':true
});
### Synerise webpush worker scope If you use **Synerise webpush** and need to set a custom service worker scope (registration path), you can enter that path as a parameter.
SR.init({
    'trackerKey':'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
    'webpush':{
        'service_worker_scope':'/pl/'
    }
});
### Disabling modules Additionally, if you need to **disable some Synerise modules** on a specific sub-page or domain, you can do it by specifying the parameters as below:
SR.init({
    'trackerKey':'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
    'disableWebPush':true,
    'disableDynamicContent':true,
});
### Customizing metadata You can add `` tags (for example, OG tags) to the website or modify existing ones. The new values are added to `page.visit` events. They can also be used with other features based on metadata, such as communication, recommendations, personalization, and so on. To do it, add a `customizeMetadata` function to `SR.init()`. **Example**:
SR.init({
    'trackerKey': 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
    'customizeMetadata': function (metadata) {
        metadata.size = 8;
        metadata.isExample = true;
        metadata['og:title'] = 'Sneakers';
        metadata['product:retailer_part_no'] = '1a4d3380-04d1';
        return metadata;
    }
});
Usage: - If the name of the meta key doesn't contain special characters, use the `metadata.keyName = 'keyValue'` syntax. - If the name of the meta key contains special characters, use the `metadata['key_name'] = 'keyValue'` syntax. - Up to 20 meta parameters can be returned. - The following value types are allowed: - string - number - boolean - array ### Cookie expiration By default, the `_snrs_p`, `_snrs_uuid`, and `_snrs_puuid` cookies expire after 400 days. You can change this by using the `cookieExpiration` parameter. The value is the number of days after which the cookies expire.
- If a browser's cookie expiration limit is lower than your setting, your setting is ignored. - The expiration time of the `_snrs_sa` and `_snrs_sb` cookies is 30 minutes and **cannot** be changed.
The following example sets cookie expiration time to 60 days:
SR.init({ 
    "trackerKey": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "cookieExpiration": 60
});
### Nonce for Content Security Policies Nonce (number used once) is a content attribute which can be used by Content Security Policies (CSPs) to determine if an element should be allowed. If a script doesn't have a nonce value that matches the one expected by the CSP, the script can't execute. You can add the nonce to the Synerise SDK initialization script:
SR.init({
  trackerKey: "VALUE",
  nonce: "VALUE"
});
The tracking code and any scripts that the SDK adds to the page (for example, in Dynamic Content) will have the nonce value that you add to `SR.init`
You must generate the value of the nonce yourself and make sure it matches the one expected by the CSP.
For more details on nonce and implementing it, see [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce).