# Documentation Guide

Welcome to the CrossEngage Product Documentation.

{% content-ref url="/pages/qdbQspzIh6p2g1UIF9S3" %}
[Data & Engagement Platform](/data-and-engagement-platform/data-model)
{% endcontent-ref %}

{% content-ref url="/pages/NqxnSRJvjOR6OU9kDGR9" %}
[Predictions Platform](/predictions-platform/data-model)
{% endcontent-ref %}

You can find our **API Documentation** here:

{% embed url="<https://api.documentation.crossengage.io/>" %}

You can also download a Collection of our API calls, to be imported to Insomnia here:

{% file src="/files/xrmsLS9puxyrOP4pLKcV" %}

### CrossEngage Architecture

CrossEngage Products are built on a Web-Oriented Architecture. This means that you do not need any installations or setup on your device(s), as all processing is done on our Servers. You can use an up-to-date web browser to access our products.

{% hint style="info" %}
We recommend using Google Chrome for CrossEngage products.
{% endhint %}

Additionally, CrossEngage provides APIs to interact with our servers and databases. Once you have your API keys (from your System Setup), you can use any API Client or write your own code to hit the API endpoints. In this documentation, we use Postman and Insomnia as API Clients.


# Data Model

In the CrossEngage Data & Engagement Platform, data is divided into three types; Customer, Product and Event.

### Data Formats

| Data Type            | Format                                                                                                                      |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Date/Datetime        | <p>2016-03-22</p><p>2016-04-01T18:02:42</p>                                                                                 |
| File Format          | All files csv or Json have to be encoded in utf-8 without bom                                                               |
| Float/numeric Format | <p>15.10</p><p>1015.10</p><p>(We are taking care of the thousand separator but the decimal separator needs to be a dot)</p> |
| Phone                | Please deliver Phone numbers in the international standard: [E.164](https://en.wikipedia.org/wiki/E.164)                    |
| Data Fields          | Please use camelCase for any specially created fields.                                                                      |

Dates and times are expressed in ISO8601 format in UTC (Coordinated Universal Time), with a special UTC designator ("Z"). More details on the date format can be found [here](https://www.w3.org/TR/NOTE-datetime).


# Customer Data

The Customer Data stores information about your Cutomers, as well as potential customers. This includes Personally Identifiable Information (PII) of the Customers.

### Customer Traits / Attributes

<table><thead><tr><th>Trait</th><th>Description</th><th width="139" data-type="checkbox">Mandatory</th><th>Example</th></tr></thead><tbody><tr><td>id</td><td>Unique identifier of a customer</td><td>true</td><td>ABC12345</td></tr><tr><td>customerSince</td><td>Registration date</td><td>true</td><td>2022-01-01</td></tr><tr><td>email</td><td>Email address</td><td>false</td><td>john.doe@company.com</td></tr><tr><td>firstName</td><td>First name</td><td>false</td><td>John</td></tr><tr><td>lastName</td><td>Last Name</td><td>false</td><td>Doe</td></tr><tr><td>street</td><td>Street name</td><td>false</td><td>Berliner Strasse</td></tr><tr><td>postcode</td><td>Postal Code</td><td>false</td><td>50676</td></tr><tr><td>city</td><td>City</td><td>false</td><td>Berlin</td></tr><tr><td>country</td><td>Country</td><td>false</td><td>DE</td></tr><tr><td>language</td><td>Language</td><td>false</td><td>DE</td></tr><tr><td>birthday</td><td>Date of birth</td><td>false</td><td>1999-12-06</td></tr><tr><td>gender</td><td>Gender</td><td>false</td><td>Male</td></tr><tr><td>phone</td><td>Phone number</td><td>false</td><td>0123 4567890</td></tr><tr><td>doi</td><td>Double opt-in indicator</td><td>false</td><td></td></tr><tr><td>subscriptionDate</td><td>Subscription date</td><td>false</td><td>2022-05-18</td></tr><tr><td>opt-out</td><td>Opt out indicator</td><td>false</td><td></td></tr><tr><td>lastNPSDate</td><td>Date of the latest NPS score</td><td>false</td><td>2022-05-18</td></tr><tr><td>lastNPSScore</td><td>Latest NPS score</td><td>false</td><td>8</td></tr></tbody></table>

### Example

You can upload User profiles using a JSON file. Please go to [Data Management ](/data-and-engagement-platform/data-management)to learn more.

```javascript
[
   {
       "id": "ABC12345",
       "customerSince": "2022-01-01",
       "birthday": "1981-01-31",
       "gender": "Female",
       "email": "abc@def.com",
       "country": "DE"
   },
   {
       "id": "DEF6789",
       "customerSince": "2019-07-08",
       "birthday": "1972-05-18",
       "gender": "Male",
       "email": "a12@xyz.de",
       "country": "DE"
   }
]

```


# Product Catalogue

The Product Catalogue stores a complete record of the products you offer, along with their properties such as price or image.

### Product Properties

<table><thead><tr><th>Property</th><th>Description</th><th data-type="checkbox">Mandatory</th><th>Example</th></tr></thead><tbody><tr><td>sku</td><td>The stock keeping unit of a product (required)</td><td>true</td><td></td></tr><tr><td>id</td><td>Identifiers other than SKU which you would like to pass on to CrossEngage can be submitted through this field. This is a simple text field cannot be used as a CrossEngage product identifier</td><td>false</td><td></td></tr><tr><td>title</td><td>The product name</td><td>false</td><td></td></tr><tr><td>description</td><td>A description of the product</td><td>false</td><td></td></tr><tr><td>link</td><td>The full URL to a product page</td><td>false</td><td></td></tr><tr><td>bigImageLink</td><td>The full URL of a high resolution image of the product</td><td>false</td><td></td></tr><tr><td>smallImageLink</td><td>The full URL of a thumbnail image of the product</td><td>false</td><td></td></tr><tr><td>category</td><td>The category of a product. Can be used for a single category or for combining multiple categories in a single string, for example using breadcrumbs style: Clothes → Jeans</td><td>false</td><td></td></tr><tr><td>price</td><td>Price of a product (without currency)</td><td>false</td><td></td></tr><tr><td>salesPrice</td><td>Can be used to store the advertised sale price of a product. This is a simple numeric field, CrossEngage does not assign any internal logic to it</td><td>false</td><td></td></tr><tr><td>salesPriceEffectiveDate</td><td>Date from which the salesPrice applies. No logic is assigned to this field</td><td>false</td><td></td></tr><tr><td>discount</td><td>A human-readable description of the discount on the salesPrice (for example €20 or -20%)</td><td>false</td><td></td></tr><tr><td>currency</td><td>Currency of the numeric price values</td><td>false</td><td></td></tr><tr><td>stockQuantity</td><td>Number of items in stock</td><td>false</td><td></td></tr><tr><td>enabled</td><td>Can be used to mark products as enabled (1) or disabled (0). No internal logic is assigned to this field.</td><td>false</td><td></td></tr><tr><td>attributes</td><td>An object to store custom attributes. At the moment, only simple data types are supported (no arrays or objects). You can flatten your data before adding where necessary, e.g. instead of "categories": ["Men", "Shirts"] use "category1": "Men", "category2": "Shirts".</td><td>false</td><td></td></tr></tbody></table>

### Example

You can upload a Product Catalogue using a JSON file. Please go to [Data Management ](/data-and-engagement-platform/data-management)to learn more.

```javascript
{
   "id": null,
   "sku": "3938-691-926",
   "title": "Puke Duke",
   "description": "Das Bier mit Zimt-Vanille-Geschmack.\nInhalt:\n- Eine Dose à 0,5 Liter.",
   "link": null,
   "bigImageLink": "https://abload.de/img/puke_dukevxke2.jpg",
   "smallImageLink": "https://abload.de/thumb/puke_dukevxke2.jpg",
   "category": "Getränke → Bier",
   "price": 1.09,
   "salesPrice": null,
   "salesPriceEffectiveDate": null,
   "discount": null,
   "currency": "€",
   "stockQuantity": 120,
   "enabled": 0,
   "attributes": {
       "brand": "Duke"}}
```


# Events

The Event Stream collects and logs events in the CrossEngage system. These events can be collected from your website, your Outbound communications, or customer transactions. You can also upload events to the CrossEngage system. Please go to [Data Management ](/data-and-engagement-platform/data-management)for more information.

Custom Events can also be created. If you would like to create Custom Events, please contact your Customer Success Manager.

### Predictions and Modelling

For creating Predictions and Models ( Neural Networks ), it is important to have sufficient quantity and quality of data. It is strongly recommended to provide all events (especially all orders) for Predictions, including from Customers who have churned, or opted out of communications.

For reliable predictions, event history of 5 years or more is generally considered sufficient. However, this is not a hard rule as other factors, such as feature selection or data quality can also affect the output of a Model. If there is any confusion, please reach out to your respective Customer Success Manager, or [write us a Ticket](/data-and-engagement-platform/help-and-support/reach-out-to-customer-support).


# Onsite Events

Onsite Events are Events created when a Customer interacts with your website or online store. You can add a script to your website to capture these Events in CrossEngage automatically. For more information, please see [Web Tracking](/data-and-engagement-platform/web-tracking).

### Events

We can roughly divide Onsite events into 4 categories:&#x20;

* UserID Events
* View Events
* Product Events
* Coupon Event

Note that Orders placed on your website are considered Transactions.

{% tabs %}
{% tab title="UserID Events" %}

* User Login
* User Logout
* Identified
* Registered
  {% endtab %}

{% tab title="View Events" %}

* Viewed Page
* Viewed Cart
* Viewed Product
  {% endtab %}

{% tab title="Product Events" %}

* Added Product
* Removed Product
* Reviewed Product
* Filtered Product
* Wishlisted Product
* Wishlist removed Product
  {% endtab %}

{% tab title="Coupon Events" %}

* Coupon Entered
* Coupon Applied
* Coupon Denied
* Changed Checkout Status
  {% endtab %}
  {% endtabs %}

### Properties

All Onsite Events have two base properties: User\_id and timestamp. Additionally, based on the Event, it could also have **Cart**, **Product** and **Page** Properties.

<table><thead><tr><th>Property</th><th>Description</th><th data-type="checkbox">Mandatory</th><th>Example</th></tr></thead><tbody><tr><td>User_id</td><td>Unique identifier</td><td>true</td><td>ABC12345</td></tr><tr><td>timestamp</td><td>Event date / time</td><td>true</td><td>2022-01-01</td></tr></tbody></table>

{% hint style="info" %}
While the two base properties are common, events may or may not posses Cart, Product and page properties. If you need any help regarding events and properties, please [write us a ticket](/data-and-engagement-platform/help-and-support/reach-out-to-customer-support).
{% endhint %}

#### Cart Properties

| Property            | Description                           |
| ------------------- | ------------------------------------- |
| total               | Total value of the cart               |
| currency            | Currency                              |
| products            | products present in the cart          |
| numberOfItems       | total number of all items in the cart |
| numberOfUniqueItems | number of unique items in the cart    |

#### Page Properties

| Property | Description                                     |
| -------- | ----------------------------------------------- |
| url      | URL of the webpage                              |
| title    | Title of the webpage                            |
| path     | path to the visited page                        |
| referrer | The webpage from which this resource is visited |
| language | Language of the webpage                         |
| location | URL of the page                                 |

#### Product Properties

| Property | Description                                          |
| -------- | ---------------------------------------------------- |
| category | Product category                                     |
| brand    | Product brand                                        |
| sku      | Stock Keeping Unit, unique identifier of the product |
| name     | Product name                                         |
| currency | Currency of payment                                  |
| price    | Price per unit                                       |
| quantity | Quantity                                             |
| id       |                                                      |

### Examples

You can upload these events using the CrossEngage API, or via the Event Feed. Please go to [Data Management ](/data-and-engagement-platform/data-management)to learn more.

Here is an example of the JSON used to upload an event via the API.

```javascript
{
   "id": "78ad0e3e-19e6-4ec1-84a7-b2c860c05387",
   "timestamp": "2021-10-22T09:21:06Z",
   "events": [{
           "event": "Added Product",
           "properties": {
               "cart": {
                   "total": 150,
                   "currency": "EUR",
                   "numberOfItems": 3,
                   "numberOfUniqueItems": 1,
                   "products": [{
                           "id": "507f1f77bcf86cd879439023",
                           "sku": "61979589",
                           "brand": "Happy",
                           "title": "Zegna Shirt",
                           "name": "Striped Shirt",
                           "price": 50,
                           "quantity": 3,
                           "category": "Shirts",
                           "currency": "EUR"
 }]}}}]}
```

Here is the same example, presented as a JSON file that can be uploaded via Data Feeds:

```javascript
[{
       "event": "Added Product",
       "id": "78ad0e3e-19e6-4ec1-84a7-b2c860c05387",
       "timestamp": "2021-10-22T09:21:06Z",
       "cart": {
           "total": 150,
           "currency": "EUR",
           "numberOfItems": 3,
           "numberOfUniqueItems": 1,
           "products": {
                   "id": "507f1f77bcf86cd879439023",
                   "sku": "61979589",
                   "brand": "Happy",
                   "title": "Zegna Shirt",
                   "name": "Striped Shirt",
                   "price": 50,
                   "quantity": 3,
                   "category": "Shirts",
                   "currency": "EUR"
}}}]
```


# Outbound Events

Outbound events relate to outbound communications to your customers, such as emails and push notifications. These events store information about the messages, as well as customer interactions with these messages, such as opening an email.

Note that CrossEngage automatically collects events for messages sent out via CrossEngage Integrations. However, if you are using other outbound communication services, you should upload these events to the CrossEngage system.

### Events

* Message Sent
* Message Delivered
* Message Viewed
* Message Clicked
* Message Unsubscribed
* Message soft\_bounced
* Message hard\_bounced
* Message marked\_as\_spam

{% hint style="warning" %}
Different Third Party Providers might only support a subset of these events. For example, the Episerver (Optimizely) Integration provides Message Sent event, but does not provide Message Delivered Events.
{% endhint %}

### Properties

<table><thead><tr><th width="145">Properties</th><th width="272">Description</th><th width="123" data-type="checkbox">Mandatory</th><th>Example</th><th data-hidden></th></tr></thead><tbody><tr><td>User_id</td><td>Unique identifier for each customer</td><td>true</td><td>ABC12345</td><td></td></tr><tr><td>timestamp</td><td>The date and time of the event</td><td>true</td><td>2022-01-01</td><td></td></tr><tr><td>channel</td><td>Channel used to send the message</td><td>false</td><td>Email</td><td></td></tr><tr><td>type</td><td>categorization of the message</td><td>false</td><td>Newsletter</td><td></td></tr><tr><td>url</td><td>URL</td><td>false</td><td></td><td></td></tr><tr><td>campaign_id</td><td>Campaign Identified</td><td>false</td><td>123456</td><td></td></tr><tr><td>message_id</td><td>Message identifier</td><td>false</td><td>304405</td><td></td></tr></tbody></table>

### Examples

You can upload these events using the CrossEngage API, or via the Event Feed. Please go to [Data Management ](/data-and-engagement-platform/data-management)to learn more.

Here is an example of the JSON used to upload two events via the API.

```javascript
{
   "id": "ABC12345",
   "events": [{
           "event": "Message Sent",
           "timestamp": "2022-01-11T00:00:00Z"
          "properties": {
               "channel": "Email",
               "type": "Newsletter"
           }},
       {
           "event": "Message Delivered",
           "timestamp": "2022-01-11T00:00:00Z"
          "properties": {
               "channel": "Email",
               "type": "Newsletter"
           }}]}

```

Here is the same example, presented as a JSON file that can be uploaded via Data Feeds:

```javascript
[
   {
       "id": "ABC12345",
       "event": "Message Sent",
       "timestamp": "2022-01-11T00:00:00Z",
       "channel": "Email",
       "type": "Newsletter"
   },
   {
       "id": "ABC12345",
       "event": "Message Delivered",
       "timestamp": "2022-01-11T00:00:00Z",
       "channel": "Email",
       "type": "Newsletter"
   }
]
```


# Transactions

Transactions are events which relate to the sale of products and services. Generally, these include Orders and Cancellations / Returns. These events are key, as revenue is generated here, and are vital for Modelling and Predictions.

### Events

| Event                | Description                      |
| -------------------- | -------------------------------- |
| Completed Order      | An order is placed               |
| Changed Order Status | An order is cancelled / returned |

For contractual businesses, CrossEngage also has the following events:

<table><thead><tr><th width="211.5">Event</th><th>Description</th></tr></thead><tbody><tr><td>contract_sale</td><td>Conclusion of a contract</td></tr><tr><td>contract_start</td><td>start of the contract</td></tr><tr><td>contract_cancellation</td><td>The contract is cancelled</td></tr><tr><td>contract_end</td><td>The contact expires</td></tr><tr><td>contract_return</td><td>the contract is cancelled during trial phase</td></tr></tbody></table>

### Properties

Order events have three base properties, as well as Cart properties. Cart properties can be accessed by using cart.products\[***product\_number***].***property.***

<table><thead><tr><th width="234">Property</th><th>Description</th><th width="108" data-type="checkbox">Mandatory</th><th>Example</th></tr></thead><tbody><tr><td>id</td><td>Unique Identifier</td><td>true</td><td>DEF12345</td></tr><tr><td>timestamp</td><td>Event date</td><td>true</td><td>2022-01-01</td></tr><tr><td>orderId</td><td>Invoice ID</td><td>true</td><td>1234</td></tr><tr><td>cart.products[].id</td><td>Invoice item number</td><td>true</td><td>1</td></tr><tr><td>cart.products[].quantity</td><td>quantity of item</td><td>true</td><td>4</td></tr><tr><td>cart.products[].price</td><td>price per unit</td><td>true</td><td>10.99</td></tr><tr><td>cart.products[].category</td><td>Product Category</td><td>false</td><td>Shoes</td></tr><tr><td>cart.product[].brand</td><td>Product brand</td><td>false</td><td>Samsung</td></tr><tr><td>cart.products[].sku</td><td>Product SKU</td><td>false</td><td>AB1234</td></tr><tr><td>cart.products[].name</td><td>Product name</td><td>false</td><td>Cap</td></tr><tr><td>cart.currency</td><td>Currency of payment</td><td>false</td><td>Euro</td></tr></tbody></table>

### Examples

You can upload these events using the CrossEngage API, or via the Event Feed. Please go to [Data Management ](/data-and-engagement-platform/data-management)to learn more.

Here is an example of the JSON used to upload two events via the API.

```javascript
{
  "id": "ABC12345",
  "events": [{
          "event": "Completed Order",
          "timestamp": "2022-01-01T09:21:06Z",
          "properties": {
              "orderId": "1234",
              "cart": {
                  "total": 46.13,
                  "currency": "EUR",
                  "numberOfItems": 3,
                  "numberOfUniqueItems": 2,
                  "products": [{
                          "id": "1",
                          "price": 10.99,
                          "quantity": 1,
                          "category": "T-shirt"
                  },{
                          "id": "2",
                          "price": 17.57,
                          "quantity": 2,
                          "category": "Shoe"
                  }]
              }
          }
        }, {
          "event": "Changed Order Status",
          "timestamp": "2022-01-01T09:21:06Z",
          "properties": {
              "orderId": "1234",
              “status”: “return”,
              "currency": "EUR",
              “id”: “1”,
              "price": 10.99,
              "quantity": 1,
              "category": "T-shirt"
	  }
	}]
}
```

Here is the same example, presented as a JSON file that can be uploaded via Data Feeds:

```javascript
[{
   "event": "Completed Order",
   "id": "ABC12345",
   "timestamp": "2022-01-01T09:21:06Z",
   "orderId": "1234",
   "cart": {
       "total": 46.13,
       "currency": "EUR",
       "numberOfItems": 3,
       "numberOfUniqueItems": 2,
       "products": [{
               "id": "1",
               "price": 10.99,
               "quantity": 1,
               "category": "T-shirt"
           },
           {
               "id": "2",
               "price": 17.57,
               "quantity": 2,
               "category": "Shoe"
           }]}}
{
   "event": "Changed Order Status",
   "id": "ABC12345",
   "timestamp": "2022-01-01T09:21:06Z",
   "orderId": "1234",
   “status”: “return”,
   "currency": "EUR", 
    “id”: “1”,
   "price": 10.99,
   "quantity": 1,
   "category": "T-shirt"
}]
```


# App User Management

CrossEngage helps you limit access of certain features and data for members of your team, based on their role. In this section, you can learn to create and manage App Users, and restrict their permissions based on their job roles.


# User Roles

The Role of a User determines what the user can and cannot do within the CrossEngage platform. To see your role, you can click on your profile picture in the top right corner, and go to your Profile. Administrators can also choose roles for other app users.

### Standard User Roles

Go to `Settings` -> `User Roles`. Here you can see a summary of the 6 Standard User Roles, and number of Users in each Role. Click on any role to see its description, and permissions granted to the role.

<figure><img src="/files/f2WGFwQUlMbZD4nNcsnl" alt=""><figcaption><p>Permissions for the User Role "Administrator"</p></figcaption></figure>

**Administrator** has full control over the Campaigns and User Segments tabs. It is the only role enabling you to see the Settings tab and make changes within it.

**Campaign Manager** has a full control over the Campaigns and User Segments tabs. As a campaign manager you can, for example, create or edit segments and create, edit and activate campaigns.

**Campaign Manager (No PII)** has the same abilities as the Campaign Manager, however without being able to see the personally identifiable information of your customers. For example, you will not be able to see the list of the people in your segments, just their total number.

**Restricted Campaign Manager** can create and edit segments and create and edit campaigns, however, cannot activate campaigns. This is the only distinction between this role and the full-fledged Campaign Manager.

**Analyst** can read all campaigns and segments, but cannot edit or create them. This role is meant for users that are interested in performance and reporting, but do not need to set up campaigns or segments themselves.

**Analyst (No PII)** has the same abilities as Analyst, however without being able to see the personally identifiable information of your customers.

<figure><img src="/files/SUZZVj2LX10Ol0FPFLvn" alt=""><figcaption><p>An Overview for Permissions for standard User Roles</p></figcaption></figure>


# App Users

To manage App Users on the CrossEngage Platform, go to **Settings -> App Users**. Here you can view App User Profiles, create or edit App Users, or deactivate their accounts.

<figure><img src="/files/eYFYtZVH0zk2PMyOUt2b" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
To view and edit App Users, make sure you are logged into an Administrator account.
{% endhint %}

### **Creating an App User**

You can add new App Users when someone new joins your team.

* In the App Users page, click on `Create New User` in the top right of the screen.
* Fill out all details for this user, including their role.
* Click `Save`.

<figure><img src="/files/is6Gf8OSK5pxFpw45KKh" alt=""><figcaption></figcaption></figure>

### **Editing an App User**

You can change User Details and Reset Passwords as necessary using this option.

* In the App Users page, click on the User you wish to edit in the App Users list. This will open their profile.
* Click on the `Edit Profile` button.
* Edit the profile details. You can also click on `Reset Password` to recover an App User if they have forgotten their password.
* Click `Save`.&#x20;

### **Deactivating an App User**

If you would like to remove access to the platform for an App User (for example, if they leave your team), you can Deactivate that user.

* In the App Users page, click on the User you wish to edit in the App Users list. This will open their profile.
* Click the three dots **`. . .`** next to the User Profile button. Click on the `Deactivate` button that appears.
* A window will pop up, to confirm whether to deactivate the App User. Click on the `Deactivate` button.
* Similarly, you can click on an Inactive Profile, then use the `Activate` button to Reactivate the App User.

<figure><img src="/files/UGzPN0Riz16nf6JDR4DR" alt=""><figcaption></figcaption></figure>


# Data Management

CrossEngage stores User, Product and Event data on the platform. In this section, you can learn how to manage your User Database, Product Catalogue and Events, and how to import this data when you first join the CrossEngage platform.

CrossEngage offers two methods for managing these Databases - using the API or by uploading a file to an SFTP folder. The SFTP folder is the faster and easier method to manage or import data in bulk, while the API is better suited for writing, modifying or deleting individual records from the database(s).

{% hint style="info" %}
Please note that all data feeds (Users, Products, Events) need to be in **UTF-8**.
{% endhint %}


# Data Management with API

CrossEngage provides direct API access to your data stored on the CrossEngage Platform. This method is faster than Uploading a JSON for a few records, as it has the benefit of recieving responses from the API in Real-time.

To test the CrossEngage API, you can use an API Client Application such as Postman or Insomnia. You can learn more about Postman [here](https://learning.postman.com/docs/getting-started/introduction/).

For using the API, please see our [API Documentation](https://api.documentation.crossengage.io/).

### API Collections

You can download our API Collection as a file, and import it in Insomnia or Postman to start using the API directly:

{% file src="/files/e8Y7R7JgjeI4VAnqheMU" %}

Additionally, you can find API calls for the Product Feed in this collection:

{% file src="/files/w9lrKREDbb5zgmMfpCgS" %}


# Data Management with Data Feeds

CrossEngage allows you to import or manage your Data by uploading JSON files to an SFTP location. This method is quite useful for managing data in bulk, as a single JSON can be processed with a large number of records.

{% hint style="info" %}
Before uploading a file, please compress it using **gzip / zip** compression (.gz).
{% endhint %}

### Managing Data Feeds

On the CrossEngage Platform, go to `Settings` -> `System Setup`.

Click on `User Feed`.

Select the Protocol for connecting to your server, where the JSONs will be uploaded. CrossEngage supports FTP, SFTP and FTPS for your file server.

Enter your authentication information (Username and Password) for the server.

Click on `Enable Feed`, and `Save Changes`.

Similarly, repeat the process for your Product Feed.

<figure><img src="/files/Iva2MWrfmI1muauTaKWU" alt=""><figcaption></figcaption></figure>

CrossEngage systems check for new files uploaded to the Server multiple times every hour. When a new file is found, it is added to a queue to be processed. You can see when CrossEngage processes a new file in the [Activity Log](/data-and-engagement-platform/system-monitoring/activity-log). After processing, files are moved to the "Processed" folder, where they are automatically deleted after 10 days.


# Users

The CrossEngage Platform stores User Data, such that each User can be identified by their Email Address and Business Unit, or External ID (**ID**). This is important, so that Orders and Events can be linked to individual users.

### General limitations:

When creating or importing Users, please adhere to the following limitations:

* String fields **cannot** be bigger than **16 KB**. To transmit more data, please send it as an array of strings, or numbers (or other primitive types).
* The maximum size of a JSON-User object **cannot** exceed **1 MB**.
* There is a limitation of **30** nested fields for one CrossEngage instance.
* Nesting deeper than **two** levels is not possible.
* The **maximum** number of json objects that a single document/customer can contain across all fields and nested types is **1000.** This limit helps to prevent out of memory errors when a document contains too many nested objects.


# Import Users

To import Users via Secure folder, you can upload two JSON files, a header file and a data file, to the File Server. You can find credentials for the Server in your System Setup.

The header file contains the data fields structure, so that CrossEngage can validate each field on upload, to ensure there are no mistakes. The data file contains the Users and their attributes that you wish to upload to the CrossEngage system.

### Naming convention

The naming convention for these 2 files is the following:

```
user_feed_header_YYYYMMDDHHMMSS.json
user_feed_data_YYYMMDDHHMMSS.json
```

&#x20;Example:

```
user_feed_header_20180321110559.json
user_feed_data_20180321110559.json
```

{% hint style="warning" %}
Please ensure that a pair of header and data files always have the same timestamp in the UTC Timezone (`YYYMMDDHHMMSS`). If the files have different timestamps, they will not be processed as intended.
{% endhint %}

## Header File

This header file contains an array of objects which describe the type of attributes that may be loaded through a user object in the data file. The structure of these objects is as follows:

| Key           | Description                                                                                                                                                                                                                                         |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `column_name` | Name of the user attribute loaded through the user data file. The column name should always be sent in **camelCase** e.g. `firstName`                                                                                                               |
| `data_type`   | This describes the type of data that will be loaded in the respective attribute. See all possible values in the **Supported data** types section below.                                                                                             |
| `is_nullable` | This property allows you to describe whether or not a field can have the value `NULL`. Our system will automatically validate this to ensure that users will be updated correctly. Please note that the `id` field is mandatory and cannot be NULL. |

### **Supported data types**

{% hint style="warning" %}
Should your data file include any array attributes, please make sure to create these via API before uploading the file to our system to prevent our system from rejecting your file.
{% endhint %}

| Data type   | Description                  | Example                  |
| ----------- | ---------------------------- | ------------------------ |
| `text`      | strings of different lengths | `Some characters`        |
| `date`      | A date e.g. birthdate        | `2016-03-22`             |
| `timestamp` | timestamp                    | `2016-04-01T18:02:42+01` |
| `boolean`   | logical                      | `true`                   |
| `integer`   | an integer number            | `42`                     |
| `numeric`   | any number                   | `18.5`                   |

### **Example header file**

```
[
   {
      "column_name":"id",
      "data_type":"text",
      "is_nullable":"NO"
   },
   {
      "column_name":"email",
      "data_type":"text",
      "is_nullable":"YES"
   },
   {
      "column_name":"businessUnit",
      "data_type":"text",
      "is_nullable":"YES"
   },
   {
      "column_name":"firstName",
      "data_type":"text",
      "is_nullable":"YES"
   },
   {
      "column_name":"lastName",
      "data_type":"text",
      "is_nullable":"YES"
   },
   {
      "column_name":"birthday",
      "data_type":"date",
      "is_nullable":"YES"
   },
   {
      "column_name":"gender",
      "data_type":"text",
      "is_nullable":"YES"
   }
]
```

## Data File

This data file contains an array of objects which contain the data of the users that should be loaded into CrossEngage. Each object defines the attributes of a single user.

{% hint style="info" %}
The only technical mandatory field in User data is the `id`. The `id` refers to the user identifier you have assigned to a customer in your data warehouse. This is the same `id` you might be already sending through our Tracking SDK or User Management API.

But the combination of `email` and `businessUnit` of a user is also a unique identifier and therefore its advised to also include it in the user feed.&#x20;
{% endhint %}

{% hint style="warning" %}
If `email` and/or `businessUnit` are empty or missing from the import file, the importer will update them as empty and overwrite whatever there might have been saved before in the user profile.
{% endhint %}

{% hint style="warning" %}
Please note that if you drop more than one file at the same time before they are processed, only the most recent file will be processed. The older one(s) will be ignored.
{% endhint %}

### **Example data file**&#x20;

```
[
    {
      "id": "JD1534",
      "gender": "male",
      "firstName": "James",
      "email": "james.dean@yahoo.com",
      "businessUnit":"crossengage",
      "birthday": "1931-02-08",
      "lastName": "Dean",
      "lastOperation": {
          "operationDate": "2016-08-20",
          "type": "PURCHASE"
      },
      "subscriptions": [
          {
              "subscriptionId": "BI934",
              "subscriptionName": "BILD daily"
          },
          {
              "subscriptionId": "FA772",
              "subscriptionName": "FAZ weekly"
          }
      ],
      "tags": ["tag1", "tag2"]
    },
    {
      "id": "JD1332",
      "gender": "female",
      "firstName": "Marilyn",
      "email": "marilyn.monroe@gmail.com",
      "businessUnit":"crossengage",
      "birthday": "1926-01-06",
      "lastName": "Monroe",
      "subscriptions": [
          {
              "subscriptionId": "SZ337",
              "subscriptionName": "SZ weekly"
          }
      ]
    }
]
```


# Update or Delete a User Trait via File Upload

If you wish to change information about a User after they have been uploaded to the CrossEngage Platform, you can upload a JSON file with the new value of the respective trait. To identify the User, please use the `id` field, so CrossEngage can identify the correct User to update.

If you rather wish to delete a trait for a user, upload a user feed data file with `xng-delete-trait` as the value of the trait that should be deleted for that user.

{% hint style="warning" %}
Note that xng-delete-trait works only for string fields.
{% endhint %}

```
[
 {
  "id": "123786543",
  "email": "james.dean@yahoo.com",
  "businessUnit":"crossengage",
  "zipCode":"xng-delete-trait"
 }
]
```

{% hint style="info" %}
When updating User traits, since no change is being made to the Structure of the data, only the value, it is not necessary to Upload a header file.
{% endhint %}

{% hint style="warning" %}
If `email` and/or `businessUnit` are empty or missing from the import file, the importer will update them as empty and overwrite whatever there might have been saved before in the user profile.
{% endhint %}


# List of Standard User Traits/Attributes

| **Name**                                   | **Type** | **Example**                              |
| ------------------------------------------ | -------- | ---------------------------------------- |
| traits.address                             | STRING   | 304 S Test St, Apt 3B, Austin, TX, 48934 |
| traits.address.city                        | STRING   | Austin                                   |
| traits.address.country                     | STRING   | US                                       |
| traits.address.line1                       | STRING   | 304 S Test St                            |
| traits.address.line2                       | STRING   | Apt 3B                                   |
| traits.address.state                       | STRING   | TX                                       |
| traits.address.zip                         | STRING   | 48934                                    |
| traits.age                                 | INTEGER  | 45                                       |
| traits.birthday                            | DATETIME | 1975-06-27                               |
| traits.businessUnit (note: case sensitive) | STRING   | DE                                       |
| traits.city                                | STRING   | Berlin                                   |
| traits.country                             | STRING   | DE                                       |
| traits.description                         | STRING   | -                                        |
| traits.email                               | STRING   | <clara.schmidt@gmail.com>                |
| traits.externalId                          | STRING   | 29743c2f-219a-4e90-a72c-240d9a473ed9     |
| traits.feedback                            | STRING   | -                                        |
| traits.firstName                           | STRING   | Clara                                    |
| traits.gender                              | STRING   | female                                   |
| ​[traits.id](http://traits.id/)​           | STRING   | dee6365f9608653d314049583006e265         |
| traits.interested                          | STRING   | -                                        |
| traits.isIdentified                        | BOOLEAN  | true                                     |
| traits.lastName                            | STRING   | Schmidt                                  |
| traits.mobileIds                           | ARRAY    | -                                        |
| ​[traits.name](http://traits.name/)​       | STRING   | Clara Schmidt                            |
| traits.phone                               | STRING   | +4933333333333                           |
| traits.postcode                            | STRING   | 48934                                    |
| traits.title                               | STRING   | Dr.                                      |


# Products

## Introduction

When updating Products via file upload, every file is a full sync between your product database and the uploaded file:

* For each product in your file the corresponding product is updated or created in the CrossEngage product database (if the record in the CrossEngage database is older than your file).
* Products not in your file will be removed from the CrossEngage database (if the record in the CrossEngage database is older than your file).
* All products in the CrossEngage database which have an update timestamp newer than the file will be kept and not updated.

### Naming Convention

The naming convention of the file is as follows:

```
product_feed_YYYYMMDDhhmmss.json.gzip
```

Example:

```
product_feed_20200324100002.json.gzip
```

The date in the file name is important as it is used to determine its recency (and therefore whether to update products or not). The timestamp has to be in UTC. As an example, imagine the CrossEngage database currently holds two products:

* SKU-1 last updated on 2020-03-24 07:00:00
* SKU-2 last updated on 2020-03-24 10:34:00

In the above example, processing the file will update SKU-1 because its last update timestamp is older than the file. SKU-2 will not be touched because its last update timestamp is newer than the file.

This is done to resolve conflicts between API updates and feed file uploads and also to determine when to ignore a file – see below.

{% hint style="warning" %}
Please note that the product feed upload needs to be a full data upload instead of delta upload.
{% endhint %}

## File Structure

The data file must contain an array of the products to be loaded into the CrossEngage database. The only mandatory field is **sku** (stock keeping unit) which is the main product identifier in CrossEngage. Each product can also be assigned to a **businessUnit** but this is optional. Product feeds without a business unit are also perfectly valid. The combination of SKU and business unit has to be unique for a product.

### Properties

| Name                    | Data Type | Description                                                                                                                                                                                                                                                                   |
| ----------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| sku                     | String    | The stock keeping unit of a product (required)                                                                                                                                                                                                                                |
| businessUnit            | String    | Business unit a product belongs to                                                                                                                                                                                                                                            |
| id                      | String    | Identifiers other than SKU which you would like to pass on to CrossEngage can be submitted through this field. This is a simple text field cannot be used as a CrossEngage product identifier                                                                                 |
| title                   | String    | The product name                                                                                                                                                                                                                                                              |
| description             | String    | A description of the product                                                                                                                                                                                                                                                  |
| link                    | String    | The full URL to a product page                                                                                                                                                                                                                                                |
| bigImageLink            | String    | The full URL of a high resolution image of the product                                                                                                                                                                                                                        |
| smallImageLink          | String    | The full URL of a thumbnail image of the product                                                                                                                                                                                                                              |
| category                | String    | The category of a product. Can be used for a single category or for combining multiple categories in a single string, for example using breadcrumbs style: `Clothes → Jeans`                                                                                                  |
| price                   | Double    | Price of a product (without currency)                                                                                                                                                                                                                                         |
| salesPrice              | Double    | Can be used to store the advertised sale price of a product. This is a simple numeric field, CrossEngage does not assign any internal logic to it                                                                                                                             |
| salesPriceEffectiveDate | String    | Date from which the salesPrice applies. No logic is assigned to this field                                                                                                                                                                                                    |
| discount                | String    | A human-readable description of the discount on the salesPrice (for example `€20` or `-20%`)                                                                                                                                                                                  |
| currency                | String    | Currency of the numeric price values                                                                                                                                                                                                                                          |
| stockQuantity           | Integer   | Number of items in stock                                                                                                                                                                                                                                                      |
| enabled                 | Integer   | Can be used to mark products as enabled (`1`) or disabled (`0`). No internal logic is assigned to this field.                                                                                                                                                                 |
| attributes              | Object    | An object to store custom attributes. At the moment, only simple data types are supported (no arrays or objects). You can flatten your data before adding where necessary, e.g. instead of `"categories": ["Men", "Shirts"]` use `"category1": "Men", "category2": "Shirts"`. |

## Example Files

{% tabs %}
{% tab title="JSON" %}

```javascript
[{
    "sku": "3938-691-926",
    "title": "Puke Duke",
    "description": "Das Bier mit Zimt-Vanille-Geschmack.\nInhalt:\n- Eine Dose à 0,5 Liter.",
    "bigImageLink": "https://abload.de/img/puke_dukevxke2.jpg",
    "smallImageLink": "https://abload.de/thumb/puke_dukevxke2.jpg",
    "category": "Getränke → Bier",
    "price": 1.09,
    "currency": "€",
    "stockQuantity": 120
}]
```

{% endtab %}

{% tab title="XML" %}

```markup
<?xml version="1.0" encoding="UTF-8" ?>
<root>
  <row>
    <sku>3938-691-926</sku>
    <title>Puke Duke</title>
    <description>Das Bier mit Zimt-Vanille-Geschmack.
Inhalt:
- Eine Dose à 0,5 Liter.</description>
    <bigImageLink>https://abload.de/img/puke_dukevxke2.jpg</bigImageLink>
    <smallImageLink>https://abload.de/thumb/puke_dukevxke2.jpg</smallImageLink>
    <category>Getränke → Bier</category>
    <price>1.19</price>
    <currency>€</currency>
    <stockQuantity>120</stockQuantity>
  </row>
</root>
```

{% endtab %}
{% endtabs %}

## File Location and Folder Structure

* We scan the root folder of your FTP location (specified in your [Product feed settings](https://app.crossengage.io/settings/system-setup)) for new feed files.
* The file will be moved to the /processed folder if
  * it has been successfully processed. If the file itself could be processed but individual products could not be updated this will be reported but we still consider the file processed.
* The file will be moved to the /error folder if
  * we could not read the file (for example because it did not contain a valid JSON or XML structure).
  * we could only partially process a file (for example where the first half of a file contains valid JSON objects but the second half contains a different structure)
  * the timestamp in the file name could not be parses (meaning we found a file with the product\_feed\_ prefix but could not read the timestamp following the prefix)
* The file will be moved to the /ignored folder if
  * the timestamp in the filename is in the future.
  * multiple files were found (in this case the newest file will be processed while the other files will be ignored)
  * Files in the root folder without the prefix product\_feed\_  will not be touched by the product feed functionality.

## Upload Frequency

File uploads should be used for the initial upload and for infrequently synchronization of the respective product databases. A maximum of one file per day is processed. More frequent updates can be performed using the [Product Feed API](https://api.documentation.crossengage.io/product-feed-api/).

{% hint style="info" %}
When using the API we still recommend performing a full synchronization by uploading a product feed file in regular intervals. This minimizes the impact of potential networking or system errors occurring during the API usage.
{% endhint %}

For implementation and testing purposes it is also possible to temporarily increase the feed file processing frequency. Please reach out to your CrossEngage contact to arrange this.

## File Processing and Error Handling

Product feed processing can end with four different results:

1. The file was fully processed and we were able to process every product in the file.
2. The file itself was fully processed but we had to skip individual products.
3. The file was partially processed, i.e. we encountered an invalid format after processing a part of the file.
4. The file was not processed at all.

For case 1 we will clean-up all products with a last modification timestamp older than the file timestamp.

For cases 2, 3 and 4 we would not perform any clean-up as there is a risk of unintentionally removing products (which were in a part of the file that could not be processed).

The results will be reported in the [Activity Log](https://app.crossengage.io/debugging/activity-log).

## Product Feed Events

{% hint style="warning" %}
The following functionality is disabled by default. Please reach out to your CrossEngage contact to have it enabled. These events can only be used in real-time user journeys and are not available for segmentation.
{% endhint %}

When a product is updated either through a product feed or through our API, CrossEngage will observe changes in either the **stockQuantity** field or the **price** field of each product. If any of these values change, we emit the events listed below. When using these events in the user journeys of real-time campaigns, keep in mind that the journey builder does not validate the journey logic.

When submitting other product-related events such as Added/Removed Product or Added/Removed to Wishlist to CrossEngage, you will need to include the sku of the respective product on the top level of your event payload. This allows you to combine these events with the events generated by CrossEngage in real-time campaign user journeys.

### Product Back In Stock

This event is triggered when the stock quantity is not empty and changes from 0 to 1 or more. No event will be triggered in other cases, for example where a product was not available in previous product feeds but becomes available again or where the stock quantity value was not available and becomes available again.

The following event properties are available in user journeys and real-time campaign messages:

| **Property**           | **Description**                     |
| ---------------------- | ----------------------------------- |
| sku                    | The sku of the product              |
| currency               | The currency of the product         |
| updatedAt              | The timestamp of the product update |
| title                  | The product title                   |
| previous.stockQuantity | The previous stock quantity         |
| stockQuantity          | The current stock quantity          |
| price                  | The current price of the product    |

### Product Low Stock

This event is triggered when the stock quantity is not empty and changes from 6 or more to 5 or less. The following event properties are available:

| **Property**           | **Description**                     |
| ---------------------- | ----------------------------------- |
| sku                    | The sku of the product              |
| currency               | The currency of the product         |
| updatedAt              | The timestamp of the product update |
| title                  | The product title                   |
| previous.stockQuantity | The previous stock quantity         |
| stockQuantity          | The current stock quantity          |
| price                  | The current price of the product    |

### Product Price Increased

This event is triggered when the price for a product is available and increases. Any increase will trigger this event, even if it is just a cent. The following event properties are available:

| Property                    | Description                                |
| --------------------------- | ------------------------------------------ |
| sku                         | The sku of the product                     |
| currency                    | The currency of the product                |
| updatedAt                   | The timestamp of the product update        |
| title                       | The product title                          |
| stockQuantity               | The current stock quantity                 |
| price                       | The current price of the product           |
| previous.price              | The previous price of the product quantity |
| percentage.price.difference | The relative price difference              |
| absolute.price.difference   | The absolute price difference              |

### Product Price Reduced

This event is triggered when the price for a product is available and decreases. Any decrease will trigger this event, even if it is just a cent. The following event properties are available:

| Property                    | Description                                |
| --------------------------- | ------------------------------------------ |
| sku                         | The sku of the product                     |
| currency                    | The currency of the product                |
| updatedAt                   | The timestamp of the product update        |
| title                       | The product title                          |
| stockQuantity               | The current stock quantity                 |
| price                       | The current price of the product           |
| previous.price              | The previous price of the product quantity |
| percentage.price.difference | The relative price difference              |
| absolute.price.difference   | The absolute price difference              |

With each upload, all existing products are updated and new products are added. All products which have not been re-uploaded during the latest import are marked as deleted. They are not completely erased from our database, however they are flagged as inactive. Therefore, if you wish to keep these products active, please make sure you upload them during each import.&#x20;

**Important**: Uploading the product feed with several new products will result in deletion of all your existing products. Your product feed will then contain only those new products you imported with the last product feed.


# Events

The CrossEngage event feed can handle two types of files; Event History and Order History. In the Order History file, you can upload a list of your orders, while the event history file can also contain more details about other events.

Note: Event feed uploads are limited in size to 100,000 lines (approximately 35MB).

In order to expedite the uploading process, it is possible to upload multiple event feed files simultaneously, provided that the files have different timestamps.

{% hint style="info" %}
To configure your event feed, please contact your CrossEngage customer experience team.
{% endhint %}


# Import Orders

The purpose of the Historical Order Feed is to provide order data that you would like to use in your marketing activities with CrossEngage. The imported feed will create the following events:

* “Completed Order” events which will state that an order has been placed
* “Ordered Item” events

Furthermore, it is possible to use Order Feed to generate general events that you wish to use with CrossEngage and which are not sent via Web Tracking or Public API.&#x20;

If you are using the order feed for your orders, please note that this is not real-time, so we highly recommend Web Tracking or API for real-time activity.

The file you have uploaded will be processed with a cronjob which will run every 15 minutes. We suggest however to upload your order feed if needed hourly instead.

#### Naming Convention

The naming convention for the order file is the following:

```
“order_history_”+YYYYMMDDHHMMSS.json (UTC)
```

### Order History File

This data file contains an array of objects which contain the data of the users that should be loaded into CrossEngage. Each object defines the attributes of a single user.

In case you use multiple stores with a separate SKU or ID logic each, you will need to include a business unit that the product belongs to. The combination of business unit and Order ID needs to be unique in that case.

The .JSON file consists of an array of objects . Each of these objects represents one order will have the default keys shown below:

| Key       | Description                                                            | Data Type                              | Required | Example                        |
| --------- | ---------------------------------------------------------------------- | -------------------------------------- | -------- | ------------------------------ |
| event     | Name of the Event you’re sending                                       | string                                 | yes      |                                |
| orderId   | ID of the order                                                        | string                                 | yes      | SK13332                        |
| id        | ID of the purchasing customer (should be the same as in the User Feed) | string                                 | yes      | DE85328                        |
| timestamp | The timestamp of the order.                                            | Datetime (YYYY-MM-DD hh.mm.ss.μμμ+UTC) | yes      | 2016-04-18 07:00:43.591+02     |
| total     | The total amount of the order in currency                              | float                                  | yes      | 49.99                          |
| shipping  | The shipping fee of the order                                          | float                                  | no       | 5.00                           |
| discount  | The discount amount of the order                                       | float                                  | no       | 10.00                          |
| coupon    | The voucher code used for the order                                    | string                                 | no       | SUMMER16                       |
| currency  | The currency of the total amount of the order                          | string                                 | yes      | EUR                            |
| products  | The purchased order items                                              | array of objects                       | yes      | See 'Order Feed Example' below |
| cart      | The object containing a user's desired order items                     | array of objects                       | yes      | See 'Order Feed Example' below |

{% hint style="info" %}
The `id` refers to the user identifier you have assigned to a customer in your data warehouse and is named `externalId` in other places in the platform incl. the UI. This is the same `id` you might be already sending through our Tracking SDK or User Management API.

The combination of `email` and `businessUnit` of a user or lead is also a unique identifier and can be used instead or additionally to the external Id when importing events.
{% endhint %}

{% hint style="warning" %}
Please note that if there can be leads (users without an external Id) in the platform and you are also using the user feed import to upgrade these leads to full users (by adding the `external Id` to a profile with the matching `email` and `businessUnit`) then the user feed import needs to run first before any event- or orderfeed, or the system can't match the ids and creates new users instead.

This will not be necessary, if you include the email and businessUnit in the order events.
{% endhint %}

#### **Order File Example:**

It's possible to use more properties for each order than listed above. Please contact your account manager for this possibility.

`order_history_20160321110559.json`

```
[{
    "event" : "Completed Order",
    "orderId" : "50314b8e9bvf000000000000", 
    "businessUnit" : "DE",
    "id" : "DE62305",
    "email":"example@example.com",
    "businessUnit":"crossengage",
    "timestamp" : "2015-08-24 15:28:51.591+02",
    "cart" : {
       "total" : 24.5,
       "shipping" : 2.5,
       "numberOfUniqueItems" : 2,
       "numberOfItems" : 3,
       "currency" : "EUR",
       "products" : [
           {
              "id" : "507f1f77bcf86cd799439011",
              "sku" : "45790-32",
              "name" : "Monopoly: 3rd Edition",
              "price" : 19.0,
              "currency" : "EUR",
              "quantity" : 1,
              "category" : "Games",
              "supplier" : "Games supplier",
              "brand" : "table games"
         },
         {
              "id" : "505bd76785ebb509fc183733",
              "sku" : "46493-32",
              "name" : "Uno Card Game",
              "price" : 3.0,
              "currency" : "EUR",
              "quantity" : 2,
              "category" : "Games",
              "supplier" : "Games supplier",
              "brand" : "table games"
          }
       ]
    } 
}]
```


# Import Events

It is possible to import any other event other than orders in the Event Feed. In order to do this, the events need to have the same .JSON structure as the events that have been set up in the Web Tracking. For more information regarding pre-defined events in CrossEngage, see [here.](https://documentation.crossengage.io/tracking/user-behaviour/track-method#implementation)

Note the following requirements:

* Zip can only contain one file.
* The name of the archived file must be the same as the name of the archive. (e.g., event\_history\_20191118170500.json → event\_history\_20191118170500.json.zip)
* The requirements are not enforced on upload; if not observed, the file will be imported successfully, but marked as failed, and the zip file will not be moved.

#### Naming Convention

The naming convention for the event feed file is the following:

```
“event_history_”+YYYYMMDDHHMMSS.json (UTC)
```

### Data File

The format of the file is very similar to the order feed structure described above. On top of the listed attributes, you will need to add the following key to each entry:

| Key   | Description                      | Data Type | Required | Example               |
| ----- | -------------------------------- | --------- | -------- | --------------------- |
| event | Name of the Event you’re sending | string    | yes      | Subscribed Newsletter |

Order Feed is uploaded in the root of SFTP account. The CrossEngage importer will then add each event according to the specified name. Please ensure that the data you are providing in the Event Feed is consistent with the data you are sending with the Web Tracking.

{% hint style="info" %}
The only technical mandatory fields are the `event` and the `id`. The `id` refers to the user identifier you have assigned to a customer in your data warehouse and is named `externalId` in other places in the platform incl. the UI. This is the same `id` you might be already sending through our Tracking SDK or User Management API.

The combination of `email` and `businessUnit` of a user or lead is also a unique identifier and can be used instead or additionally to the external Id when importing events.
{% endhint %}

{% hint style="warning" %}
Please note that if there can be leads (users without an external Id) in the platform and you are also using the user feed import to upgrade these leads to full users (by adding the `external Id` to a profile with the matching `email` and `businessUnit`) then the user feed import needs to run first before any event- or orderfeed, or the system can't match the ids and creates new users instead.

This will not be necessary, if you include the email and businessUnit in the events.
{% endhint %}

#### **Event Feed Example:**

```
[
  {
    "event": "Changed Order Status",
    "orderId": "0006000384",
    "timestamp": "2018-05-22T22:00:00Z",
    "businessUnit": "DE",
    "orderType": "Click & Reserve Order",
    "numberOfUniqueItems": 1,
    "numberOfItems": 2,
    "total": 7.98,
    "discount": 0,
    "shipping": 0,
    "id": "e6bce5b3816eedd2cdd397256d6cee29d5b142ae821470c3b6883ee4b15f9499",
    "email":"example@example.com",
    "businessUnit":"crossengage"
    "cart": {
      "currency": "EUR",
      "total": 7.98,
      "products": [
        {
          "sku": "AMA0159270DE",
          "currency": "EUR",
          "quantity": 2,
          "price": 3.99,
          "name": "Ribbon Lace, B:2,5cm x L:3m, white",
          "category": "Decorative Bands",
          "id": "AMA0159270DE"
        }
      ]
    }
  }
]
```


# List of Events and Properties

You can specify custom events based on your business needs and send them via API.

The events you defined are shown in *Custom Events* section in the event list. They have to be activated for your account before you can see them in user interface of the app. Please[ submit a request](https://crossengage.atlassian.net/servicedesk/customer/portal/2) to Customer Experience team for the creation of the events you would like to send and add their exact names.

{% tabs %}
{% tab title="Added Product" %}

* **Cart Properties**
  * cart.currency
  * cart.total
  * cart.products
  * cart.numberOfItems
  * cart.numberOfUniqueItems
* **Context Properties**
  * context.language
  * context.location
  * context.page.path
  * context.page.referrer
  * context.page.search
  * context.page.title
  * context.page.url
  * context.platform
  * context.referer
  * context.siteId
  * context.userAgent
* **Further Common Properties**
  * properties.sku
  * properties.brand
  * properties.category
  * properties.id
  * properties.name
  * properties.price
  * properties.currency
  * properties.title
    {% endtab %}

{% tab title="Changed Order Status" %}

* **Cart Properties**
  * cart.currency
  * cart.product
  * cart.total
* **Common Properties**
  * properties.sku
  * properties.title
  * properties.businessUnit
  * properties.status
    {% endtab %}

{% tab title="Completed Order" %}

* **Cart Properties**
  * cart.currency
  * cart.total
  * cart.numberOfItems
  * cart.products
* **Context Properties**
  * context.language
  * context.location
  * context.page.path
  * context.page.referrer
  * context.page.search
  * context.page.title
  * context.page.url
  * context.platform
  * context.referer
  * context.siteId
  * context.userAgent
* **Further Common Properties**
  * properties.sku
  * properties.category
  * properties.currency
  * properties.name
  * properties.id
  * properties.price
  * properties.title
    {% endtab %}

{% tab title="Identified" %}

* **Context Properties**
  * context.deviceType
  * context.language
  * context.page.path
  * context.location
  * context.page.referrer
  * context.page.search
  * context.page.title
  * context.page.url
  * context.platform
  * context.referer
  * context.siteId
  * context.userAgent
* **Further Properties**
  * properties.id
  * properties.sku
  * properties.currency
  * properties.title
  * properties.category
  * properties
  * properties.voucher.code
  * properties.voucher.value
  * properties.category
    {% endtab %}

{% tab title="Registered" %}

* **Context Properties**
  * context.appVersion
  * context.deviceType
  * context.language
  * context.location
  * context.page.path
  * context.page.referrer
  * context.page.search
  * context.page.title
  * context.page.url
  * context.platform
  * context.referer
  * context.siteId
  * context.userAgent
* **Further Common Properties**
  * properties.client
  * properties.email
  * properties.firstName
  * properties.id
  * properties.lastName
    {% endtab %}

{% tab title="Removed Product" %}

* **Context Properties**
  * context.page.url
  * context.page.path
  * context.page.title
  * context.siteId
  * context.language
  * context.location
  * context.platform
  * context.referer
  * context.userAgent
  * context.page.referrer
  * context.page.search
* **Further Common Properties**
  * properties.sku
  * properties.id
  * properties.category
  * properties.title
  * properties.currency
  * properties.url
  * properties.path
  * properties.referrer
  * properties.name
  * properties.price
    {% endtab %}

{% tab title="Reviewed Product" %}
**Common Properties**

* properties.sku
* properties.brand
* properties.name
* properties.category
* properties.price
  {% endtab %}

{% tab title="Viewed Cart" %}

* **Cart Properties**
  * cart.total
  * cart.currency
  * cart.products
  * cart.numberOfItems
* **Context Properties**
  * context.language
  * context.location
  * context.platform
  * context.referer
  * context.siteId
  * context.userAgent
  * context.page.path
  * context.page.referrer
  * context.page.search
  * context.page.title
  * context.page.url
    {% endtab %}

{% tab title="Viewed Page" %}

* **Context Properties**
  * context.language
  * context.location
  * context.page.path
  * context.page.referrer
  * context.page.search
  * context.page.title
  * context.page.url
  * context.platform
  * context.referer
  * context.siteId
  * context.userAgent&#x20;
* **Further Common Properties**
  * properties.path
  * properties.referrer
  * properties.title
  * properties.url
  * properties.name
  * properties.category
  * properties.currency
    {% endtab %}

{% tab title="Viewed Product" %}

* **Context Properties**
  * context.language
  * context.location
  * context.platform
  * context.referer
  * context.siteId
  * context.userAgent
  * context.page.path
  * context.page.referrer
  * context.page.search
  * context.page.title
  * context.page.url
* **Further Common Properties**
  * properties.sku
  * properties.name
  * properties.currency
  * properties.category
  * properties.brand
    {% endtab %}
    {% endtabs %}


# Data Export

The CrossEngage API allows you to export User and Event data from the CrossEngage System. To use the API, you need an API Client Application, such as [Postman](https://learning.postman.com/docs/getting-started/introduction/).

{% hint style="info" %}
To ensure accuracy of data, the API export cannot export any events with a timestamp later than **3 hours before export** start time.
{% endhint %}

To export data via API, please check the [Export section in our API documentation](https://api.documentation.crossengage.io/export/).


# Web Tracking

The CrossEngage Web Tracking gives the opportunity to track users website behaviour with or without being logged in and properly identified, with the help of a cookie (given consent) that serves as the identifier for the CrossEngage system.&#x20;

If at a later point in time the user does get properly identified, the CrossEngage system merges the tracked behaviour of the anonymous user to the already exististing user.

{% hint style="info" %}
This cookie is considered a **First Party Cookie** because it is set to the domain of the website the tracking is inserted in and not some third party outside service. It has a lifetime of 13 months.
{% endhint %}

There are different ways to integrate Website Tracking:

* Web Tracking v1 is deprecated and will not be setup anymore
* [Web Tracking v2](/data-and-engagement-platform/web-tracking/web-tracking-v2) is the currently supported version of the CrossEngage Web Tracking. It can be setup using the [Google Tag Manager](/data-and-engagement-platform/web-tracking/web-tracking-v2/setup-using-google-tag-manager) or [without GTM](/data-and-engagement-platform/web-tracking/web-tracking-v2/setup-without-a-tag-manager).


# Web Tracking v1 (Legacy)


# Setup

To set up web tracking on your website, first you need to copy the Web Tracking code snippet from the CrossEngage app.

* Go to Settings -> System Setup.
* Click on Web Tracking, and copy the code snippet.

<figure><img src="/files/ts2heJITjL25OKODsgkj" alt=""><figcaption></figcaption></figure>

You can also copy the code below; Please make sure to add your Web-Tracking Key in the first line of the code.

{% code overflow="wrap" %}

```javascript
window.xngID = "your-tracking-key";

!function(e,n,t){function r(e){return function(){return t.push(Array.prototype.concat.apply([e],arguments)),t}}function i(){var e=document.createElement(n),t=document.getElementsByTagName(n)[0];e.async=!0,e.src="https://app.crossengage.io/analytics.min.js",t.parentNode.insertBefore(e,t)}var o,a=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","group","track","ready","alias","page","once","off","on"];if(t=e.analytics=e.analytics||[],!t.initialize)if(t.invoked)e.console&&console.error&&console.error("CrossEngage snippet included twice.");else{for(t.invoked=!0;o=a.shift();)t[o]=r(o);i()}}(window,"script");
```

{% endcode %}

#### Installing the Code Snippet

{% tabs %}
{% tab title="Using a Tag Manager" %}

* Create a tag that contains *Custom HTML*
* Once created, paste the snippet and wrap it between `<script></script>`.
* Ensure that you create or select a trigger, one that listens for a successful page load, for your newly created snippet. For **single page applications**, you will only need to **trigger the tag once**, however, for **multi page applications**, you should **trigger the tag** **on every successful page load**.&#x20;
  {% endtab %}

{% tab title="Without a Tag Manager" %}
Paste the code snippet to the \<head> of your website, wrapped in \<script>...\</script>.
{% endtab %}
{% endtabs %}

####


# Set up business Units

As your company may use different business units to differentiate activities across countries, divisions or other business entities, CrossEngage lets you add options to the tracking SDK to easily model data sent to your account. This will allow you to also track a `businessUnit` for each call made.

To set this up, copy the snippet below and paste it together with the web tracking snippet you have previously set up, changing the `businessUnit` value placeholder to the one your would like to use for tracking purposes, e.g. `DE`.&#x20;

{% code overflow="wrap" %}

```javascript
window.additionalOptions = {
	businessUnit: 'Business unit placeholder'
};
```

{% endcode %}

{% tabs %}
{% tab title="Using a Tag Manager" %}

* Copy the snippet.
* Paste it in the previously set up global tag between the `<script></script>` HTML tags after the global tracking code snippet.
* Set up a variable  for `businessUnit` that is updated dynamically to reflect the business unit for which tracking events are sent.
* Use this variable in the function options payload to update its value dynamically.
  {% endtab %}

{% tab title="Without a Tag Manager" %}

* Copy the snippet.
* Paste it in the `<head>` between the `<script></script>` HTML tags after the global tracking code snippet.
* Change the `businessUnit` dynamically to reflect the business unit for which tracking events are sent.
  {% endtab %}
  {% endtabs %}


# Tracking User Behavior


# Identify Method

### Overview

The **identify** method is used to identify, create and update users in CrossEngage. This means that anytime you can relate user's actions or attributes to a recognizable user ID, you should consider triggering identify e.g. when a user logs in, updates their profile or signs up for a newsletter.

The identify method is also used as a means to update users in the CrossEngage platform in real time and can be executed with every trait.

You do not need to call identify for anonymous visitors of your website as CrossEngage automatically assigns them an anonymous `xngGlobalUserId`.

{% hint style="warning" %}
Personal information can be sent via web tracking but we recommend to transmit sensitive information (like address, telephone etc) per API or upload via feed.
{% endhint %}

The `identify` method has the following structure:

```javascript
analytics.identify([externalId],[attributes]);
```

#### Method Parameters

| Value        | Type   | Description                                                                                                                                                                                  |
| ------------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `externalId` | string | The ID of the user you are identifying. Mandatory unless `noUserId` is present within the attributes object.                                                                                 |
| `attributes` | object | Object that contains information about the user you are creating or updating, see examples below. The key `noUserId` is mandatory if `externalId` is not included when calling the function. |

## Implementation

{% hint style="warning" %}
**id** and **email** (and also **businessUnit)** needs to be available in your data layer before you fire the request to us. If not, this might cause issues with data and will lead to incorrect mapping.
{% endhint %}

This section goes through the methods that can be used for user identification in cases where an id is known and when it is not.&#x20;

### Identify users with an id

```javascript
var externalId = '12345abcd';
var attributes = { 
    "name": "John Doe", 
    "email":"john@xng.com", 
    "plan": "tier3", 
    "logins": 10, 
    "street": "6th St", 
    "city": "Berlin", 
    "state": "Berlin", 
    "postalCode": "10557", 
    "country": "Germany" 
}; 
analytics.identify(externalId, attributes);
```

{% tabs %}
{% tab title="Using a tag manager" %}

1. Copy the snippet.
2. Create a custom HTML tag on your tag manager and paste the snippet between `<script></script>` HTML tags.
3. Set up a trigger which fires upon the form's submission
   {% endtab %}

{% tab title="Without a tag manager" %}
Using the function that listens for the form's submission, call the `identify` function with the traits shared with you.
{% endtab %}
{% endtabs %}

### Identifying a user using email

For cases when you may not have access to the `externalId`, CrossEngage allows you to identify users using `email`.&#x20;

```javascript
var attributes = { 
    "name": "John Doe", 
    "email": "john@xng.com", 
    "plan": "tier3", 
    "logins": 10
}; 

analytics.identify(attributes);
```

{% hint style="warning" %}
Please note that CrossEngage automatically fills the `businessUnit` property with an empty string when it is not provided. This will prevent the duplication of profiles with the same email address which do not have a business unit.
{% endhint %}

## Use cases

#### **A user enters their email to sign up for a newsletter and submits the form**

The `identify` call should create the user based on their email without the `externalId` field. Consider also sending the subscription status as an optional trait.

```javascript
var attributes = {
    "email": "john@xng.com",
    "noUserId": "true",
    "subscriptionStatus": "true"
}
analytics.identify(attributes);
```

#### **A user logs in using their username and password**

Upon successful login, call the identify function with a setup as per below:

```javascript
var externalId = "211519787" 
var attributes = {
    "name": "John Doe",
    "logins": 10
}
analytics.identify(externalId, attributes);
```

#### **A user signs up using their personal information**

Upon successful registration, call the `identify` function with the newly created `externalId` and any newly gathered information:

```javascript
var externalId = "211519787" 
var attributes = {
    "name": "John Doe",
    "plan": "tier3", 
}
analytics.identify(externalId, attributes);
```

You should consider sending all of the information that the user provided in their registration form so the user is set up on the CrossEngage platform in real time.

{% hint style="danger" %}
Never send any user passwords or tokens through CrossEngage web tracking functions.&#x20;
{% endhint %}

#### **A user changes their address information**

Upon form submission, call the `identify` function with the new address values:

```javascript
var externalId = "211519787" 
var attributes = {
    "address": "Bertha-Benz-Strasse 5",
    "postCode": "10557", 
    "city": "Berlin",
    "country": "Germany"
}
analytics.identify(externalId, attributes);
```

This ensures that this user's data is updated on the CrossEngage platform in real time. For example, after an update is made, direct mail campaigns can immediately have access to the most recent address information.


# Page Method

### Overview

The `page` method is used to track page views, creating `Viewed Page` events for users the function is called for. You should only trigger this method upon successful page loads or route changes in the case of single page applications. This method automatically gathers and sends information regarding the page, browser session and operating system configuration of tracked users to CrossEngage.

The `page` method has the following structure:

```javascript
analytics.page();
```

## Implementation

{% hint style="warning" %}
This page method is not needed on each page - only on those for which a specific use case might arise, e.g. sales-, special offer-, voucher-pages. You can leave out the page method on the product detail pages as the [track method](/data-and-engagement-platform/web-tracking/web-tracking-v1-legacy/tracking-user-behavior/track-method) can be used instead.&#x20;
{% endhint %}

{% tabs %}
{% tab title="Using a tag manager" %}

1. Copy the `page` method snippet.
2. Create a custom HTML tag on your tag manager and paste the snippet between `<script></script>` HTML tags.
3. Set up a trigger which fires the tag upon every page load.&#x20;
   {% endtab %}

{% tab title="Without a tag manager" %}
Call the method each time a new page is loaded.
{% endtab %}
{% endtabs %}

{% hint style="warning" %}
If you are setting up the `page` method for a single page application, ensure that you set up the trigger based on routing changes rather than page loads.
{% endhint %}

## &#x20;Gathered data

The information the `page` method transmits is stored in a `context` object, which has a syntax such as the example below:

```javascript
{ 
    language: "en-US", 
    languages: ["en-US", "en", "de"], 
    location: "https://www.crossengage.io/TPS-Report/cover/", 
    page: { 
        path: "/TPS-Report/cover/", 
        referrer: "https://www.crossengage.io/TPS-Report/", 
        search: "TPS", 
        title: "TPS Report", 
        url: "https://www.crossengage.io/TPS-Report/cover/" 
    }, 
    platform: "MacIntel", 
    siteId: "www.initech.com", 
    userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1)" 
}
```

#### Information gathered in the context object

| Value       | Type   | Description                                                                     |
| ----------- | ------ | ------------------------------------------------------------------------------- |
| `language`  | string | Current language used in the browser session.                                   |
| `languages` | array  | Array containing information the language setup of the user's operating system. |
| `location`  | string | The full URL of the tracked page.                                               |
| `path`      | string | The path of the URL of the tracked page.                                        |
| `referrer`  | string | The full URL of the page the user was previously on.                            |
| `search`    | string | Query parameters that were used on the URL.                                     |
| `title`     | string | Title of the page.                                                              |
| `url`       | string | Full URL of the page.                                                           |
| `platform`  | string | The type of operating system of the user.                                       |
| `userAgent` | string | The version and type of browser and operating system of the user.               |

## Use cases

#### Segment users that have **visited the women shoes category of your shop**

The below block is an example of a `context` object from a `Viewed Page` event which we will be targeting for this example:

```javascript
{ 
    language: "en-US", 
    languages: ["en-US", "en", "de"], 
    location: "https://www.crossengage.io/TPS-Report/cover/", 
    page: { 
        path: "/women/shoes/", 
        referrer: "", 
        search: "shoes", 
        title: "Women shoes", 
        url: "https://www.crossengage.io/women/shoes/" 
    }, 
    platform: "MacIntel", 
    referrer: "", 
    siteId: "www.crossengage.io", 
    userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1)" 
}
```

To segment all users that have visited the women shoes category of your shop, create a segment condition filtering `Viewed Page` events with the property `context.page.path` using the `contains` operator with the value `women/shoes`.

#### **Segment users that have visited the FAQ section of your site**

The below block is an example of a `context` object from a `Viewed Page` event which we will be targeting for this example:

```javascript
{ 
    language: "en-US", 
    languages: ["en-US", "en", "de"], 
    location: "https://www.crossengage.io/faq/", 
    page: { 
        path: "/faq/", 
        referrer: "", 
        search: "frequently asked questions", 
        title: "FAQ", 
        url: "https://www.crossengage.io/faq/" 
    }, 
    platform: "MacIntel", 
    referrer: "", 
    siteId: "www.crossengage.io", 
    userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1)" 
}
```

To segment all users that have visited the FAQ section of your site, create a segment condition filtering `Viewed Page` events with the property `context.page.title` using the `contains` operator with the value `FAQ`.

Depending on the use case you would like to satisfy, you may use any of the properties sent in the context of the **Viewed Page** event or even a combination of them. For example, you may want to segment all users which have visited your FAQ page, redirected from google. To segment these users, create a segment condition filtering `Viewed Page` events with the property `context.page.referrer` using the `contains` operator with the value `google` and the property `context.page.title` using the `contains` operator with the value `faq`.


# Track Method

### Overview

The `track` method is used to track any user behaviour other than identification and page views. You may track any behaviour that you would like to use to segment users in CrossEngage to use for campaigns. These can be anything from completing purchases, viewing the cart, adjusting delivery preferences to changing a products' colors in an onsite configurator.

The `track` method has the following structure:

```javascript
analytics.track([eventName],[attributes]);
```

#### Method Parameters

| Value        | Type   | Description                                                           |
| ------------ | ------ | --------------------------------------------------------------------- |
| `eventName`  | string | The name of the event your are sending to CrossEngage.                |
| `attributes` | object | Object that contains information about the event, see examples below. |

## Implementation

### Standard CrossEngage events

CrossEngage offers a range of predefined events which you can call without requiring any further event definition.

| Event                                                                                                                      | Usage                                                       |
| -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| [Viewed Product](https://documentation.crossengage.io/tracking/user-behaviour/track-method#viewed-product)                 | A user views a specific product on your website.            |
| [Added Product](https://documentation.crossengage.io/tracking/user-behaviour/track-method#added-product-removed-product)   | A user adds a product to their cart.                        |
| [Removed Product](https://documentation.crossengage.io/tracking/user-behaviour/track-method#added-product-removed-product) | A user removes a product from their cart.                   |
| [Searched Products](https://documentation.crossengage.io/tracking/user-behaviour/track-method#searched-products)           | A user uses a search bar to look for products on your shop. |
| [Completed Order](https://documentation.crossengage.io/tracking/user-behaviour/track-method#completed-order)               | A user completes a purchase.                                |
| [Viewed Cart](https://documentation.crossengage.io/tracking/user-behaviour/track-method#viewed-cart)                       | A user views their cart anywhere on your site.              |

#### Viewed Product

A user views a specific product on your website:

```javascript
var attributes = { 
    "sku": "46493-32", 
    "name": "Uno Card Games", 
    "price": 300.00, 
    "currency": "USD", 
    "category": "Games" 
}; 
analytics.track("Viewed Product", attributes);
```

#### Added Product / Removed product

A user adds a product or removes a product from their cart:&#x20;

```javascript
var attributes = {
    "sku": "16493-37", 
    "name": "Uno Card Games", 
    "price": 300.00, 
    "currency": "USD", 
    "category": "Games" ,
    "cart": {
        "products": [
            {
                "sku": "45790-32", 
                "price": 200, 
                "name": "Monopoly 3rd Edition", 
                "category": "Games", 
                "currency": "USD"
            }, 
            {
                "sku": "65112-30", 
                "price": 149.99, 
                "name": "Catan", 
                "category": "Games", 
                "currency": "USD"
            }
        ]
    }    
};
// When adding a product 
analytics.track("Added Product", attributes);
// When removing a product
analytics.track("Removed Product", attributes);
```

{% hint style="warning" %}
For **all product-related events** containing the cart object, the full current state of the cart should be passed, as the information in CrossEngage will be overwritten with each such event. The `cart` object itself is not customisable, meaning no custom attributes (like `cart.cartId`) can be added. Custom attributes can be added on the event's root level.

In addition, the sku of the respective product should be provided on the top (root) level of the event data for all product-related events. This allows using this data with Product Feed events (Product Back/Low In Stock, Product Price Increased/Reduced) in real-time campaigns.
{% endhint %}

#### Searched Products

A user uses a search bar to look for products on your shop:

```javascript
var attributes = {
  "searchTerm": "board games",
  "productsDisplayed": 10
};
analytics.track ("Searched Products", attributes);
```

#### **Completed Order**

A user completes a purchase.

{% hint style="info" %}
For each product in the `products` array, CrossEngage will trigger an additional event named`Ordered Item`. This event can be used to easily segment users that have purchased a particular item.&#x20;
{% endhint %}

{% hint style="warning" %}
Note that `sku` is mandatory for each product in the `products` array.
{% endhint %}

```javascript
var attributes = {
  "orderId": "50314b8e9bcf000000000000",
  "total": 47.68,
  "shipping": 4.5,
  "tax": 19,
  "discount": 5,
  "coupon": "hasbros",
  "currency": "USD",
  "cart": {
    "total": 40.49,
    "currency": "EUR",
    "products": [
        {
          "sku": "45790-32",
          "name": "Monopoly: 3rd Edition",
          "price": 29.50,
          "quantity": 1,
          "category": "Games"
        },
        {
          "sku": "46493-32",
          "name": "Uno Card Game",
          "price": 10.99,
          "quantity": 2,
          "category": "Games"
        }
    ]
  }
};
analytics.track("Completed Order", attributes);
```

{% hint style="info" %}
Sending **Completed Order** via Feed is recommended for historical event. Once your historical orders have been added to our system, **Completed Order** event is mostly done via API.
{% endhint %}

#### **Viewed Cart**

A user views their cart anywhere on your site. You can trigger this either on loading the full cart page or even a cart overlay that is triggered from the navigation bar.

```javascript
var attributes = {
  "cart": {
    "total": 40,
    "currency": "EUR",
    "products": [
	{
	  "sku": "12351920", 
	  "name": "Stiletto Shoes", 
	  "price": 20, 
	  "quantity": 2
	},
      {
        "sku": "46493-32",
        "name": "Uno Card Game",
        "price": 10.99,
        "quantity": 2
      }
    ]
  }
};
analytics.track("Viewed Cart", attributes);
```

### Sending custom events

The CrossEngage web tracking library allows you to also send custom events through the `track` method. To send custom events, please contact your dedicated Customer Success manager so that they can define these events and their properties for use within the CrossEngage platform.

To make it easier for us to prepare the events for you, please send your Customer Success manager the structure of the event in the following format:

```
{
    "Custom Event Name": {
        "property 1 name": string,
        "property 2 name": boolean,
        "property 3 name": [
            "child type": object
        ]
    }
}
```

The formats supported by CrossEngage are the following:

* `string`
* `integer`
* `float`
* `datetime`
* `array`
* `object`

## Use cases

**A user makes a purchase**

Using the `Completed Order` predefined CrossEngage event structure, call the `track` method with the entire cart object, including all products in the cart at the time of purchase.

{% hint style="info" %}
When a `Completed Order` event is sent to CrossEngage, it will automatically trigger an `Ordered Item` event for each of the products in the cart to allow you to easily segment users ordering particular products of a specific category or a within a specific price range.
{% endhint %}

To segment all users that have completed orders,  create a segment condition filtering `Completed Order` events. You may also use the event property `cart.total` with the operator `greater than` to additionally segment users that have completed an order over a given value.&#x20;

**A user views a cart overlay from the navbar of your site.**

Using the `Viewed Cart` predefined CrossEngage event structure, call the `track` method with the entire cart object.

{% hint style="info" %}
It is recommended that you send all products in the cart and all available product information  to ensure that you gather all relevant data for segmentation purposes.
{% endhint %}

To segment all users that have viewed their cart, create a segment condition filtering `Viewed Cart` events. You may also use the event property `cart.total` with the operator `greater than` to additionally segment only users viewing carts over a given amount.&#x20;

**A user changes the color of a shoe in an onsite configurator.**

Contact your dedicated Customer Success manager and define a custom event called, for example, `Colour Changed` with a structure as per below:

```
{
    "Colour Changed": {
        "colour": string,
        "category": string,
        "shoeSize": integer,
        "imageUrl": string
    }
}
```

Once receiving confirmation that the event is ready for use, you may now call the `track` method with a payload similar to the one below:

```javascript
var attributes = {
  "colour": "red",
  "category": "shoes",
  "shoeSize": 36,
  "imageUrl": "https://www.crossengage.io/images/catalog/product/stiletto.jpg"
};
analytics.track ("Colour Changed", attributes);
```

To segment all users that have changed their shoe color in an online configurator, create a segment condition filtering `Colour Changed` events with the property `category` using the `equals` operator with the value `shoes`.&#x20;

{% hint style="info" %}
Consider sending all the information that is relevant as this may be used for message personalization.
{% endhint %}


# Opt-Out from Tracking

### Overview

To allow users to opt-out from CrossEngage SDK tracking, our library checks if there is an opt-out cookie set in the user's browser. When a cookie is found, the library will not send any tracking requests even when corresponding functions are called, therefore no user actions will be recorded.

{% hint style="warning" %}
If the tracking library does not track user behaviour, it is unable to send any messages through the channels powered by our tracking library:

* Onsite Display
* Browser Notification
* Exit Intent
  {% endhint %}

Please note that:

* By default all users visiting your pages for the first time are opted-in.
* Whenever a user opts-out, this is only valid for the browser they are using at that time. If a user revisits the website through a different browser or device, they will be considered opted-in by the tracking library for that browser / device.
* If a user clears their cookies, the opt-out cookie will be deleted and the user will be opted-in again.
* All cookies have expiration times. Opt-out cookies created through the tracking library have an expiration time of 2 years from the creation time.

## Implementation

#### How to manage opt-out

You can either create and delete the opt-out cookie yourself or use our tracking library support functions.&#x20;

#### Create the cookie manually

To create the opt-out cookie yourself, you have to ensure that you use the exact name, otherwise our library will be unable to find it.

The name of the cookie is:

```
xng.tracking-opt-out
```

#### Create the cookie via support functions

```jsx
xng.setTrackingOptOut([isOptedOut])
```

| Value        | Type    | Description                                                                                                                 |
| ------------ | ------- | --------------------------------------------------------------------------------------------------------------------------- |
| `isOptedOut` | boolean | Provide `true` to opt-out the user from the tracking (creates an opt-out cookie) or `false` to opt-in (deletes the cookie). |

```javascript
xng.optOutTracking()
```

A convenient method to opt-out of tracking for the current browser, the same as using `setTrackingOptOut(true)`.

```javascript
xng.optInTracking()
```

A convenient method to opt-in to tracking for the current browser, the same as using `setTrackingOptOut(false)`.

```javascript
xng.isTrackingOptOut()
```

A method to check opt-out status for the current browser. Returns a boolean value: `true` if the opt-out cookie is present and `false` if not.

## Examples

To opt-out a user, first you need to install XNG library on the page, where you want to initiate the opt-out, then call `xng.optOutTracking()`.

To opt-in a user back, call `xng.optInTracking()`.


# Testing & Debugging

### Using the Browser Console

After setting up the web tracking SDK, the best way to debug it is by going on the site it was installed on and monitoring the network traffic through your preferred browser's Inspectection tool.

For example, if you are using Google Chrome, open the console by right clicking anywhere on your page and choosing `Inspect`. In order to find the events that are sent to CrossEngage, click on the `Network` tab in the top bar of the newly opened inspect area. In the search window, type `track`. Refresh the page to see all events sent to CrossEngage and continue browsing, analysing whether or not the events are triggered as expected.

<figure><img src="/files/M7Qi2LYW6Jftk4wXjyrd" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/YIeikjmFRgqVmIyJ5m6f" alt=""><figcaption></figcaption></figure>

To view the events in detail, click on the tracked event; you will see the all information of the Request that is sent to CrossEngage.

## Using the event stream

In addition to using your preferred browser's inspect tools to ensure that events are sending correctly, you can also verify this through the Event Stream feature of CrossEngage.

To monitor events in real-time, select "Event Stream" from the navigation bar.

<figure><img src="/files/0T9sgndT1LJZ8ZBWowHz" alt=""><figcaption></figcaption></figure>

Click on the Filter icon and choose "User". Here you can filter events by User XNG-ID or Session ID.

<figure><img src="/files/p8Mbjwfg3ueGzJvGZBpP" alt=""><figcaption></figcaption></figure>

If your domain is not yet authorized by CrossEngage, you will receive the following error message:

```
XMLHttpRequest cannot load https://api.crossengage.io/api/.... Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
```

In order to fix this, [please submit a ticket](/data-and-engagement-platform/help-and-support/reach-out-to-customer-support) with a request to include your website in the list of accepted domains.


# Web Tracking v2


# Setup using Google Tag Manager

Navigate your tag manager to the **workspace** overview.

Choose the **Templates** section in the menu on the left. In the **Tag Templates** section you can now choose **Search Gallery** to import our tag template.

<figure><img src="/files/8KUhuvYsVREIbCYHEd5k" alt=""><figcaption></figcaption></figure>

Searching for **CrossEngage Tracking SDK Snippet** will lead you to our tag template which is always kept up to date.

You can then add this Snippet to your workspace by clicking on **Add to workspace.**

<figure><img src="/files/1C0oW0gDApWFqSeNUPCx" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
**Please note that you have to allow the injection of scripts as well as the access of global variables in order to use the tag template.**&#x20;
{% endhint %}

Once you have added the SDK template in your GTM workspace, you can easily set up a **tag** that makes use of the SDK template, enabling the CrossEngage tracking functionality.

To set up the tracking, go to **`Tags > New > Tag Configuration`** and choose the **CrossEngage Tracking SDK Snippet** in the Custom section.

You can now enter your respective CrossEngage web tracking API key that can be retrieved from your CrossEngage admin section.

<figure><img src="/files/w6JBfUOnWT1dB6syH74O" alt=""><figcaption></figcaption></figure>

To retrieve your CrossEngage web tracking API key, log into your CrossEngage account and navigate to **`Settings > System Setup > API keys`.up**

<figure><img src="/files/H3M3wjJJIAdsgNpf5io0" alt=""><figcaption></figcaption></figure>

In this section you can find the correct web tracking API key and simply **copy paste it into your tag.**

<figure><img src="/files/GLDptxroC87J9sSCfCsK" alt=""><figcaption></figcaption></figure>


# Setup without a Tag Manager

To set up web tracking on your website, first you need to copy the Web Tracking code snippet from the CrossEngage app.

* Go to Settings -> System Setup.
* Click on Web Tracking, and copy the code snippet.

<figure><img src="/files/Ivc3KC3iTjm3JRHWo6if" alt=""><figcaption></figcaption></figure>

You can also copy the code below; Please make sure to add your Web-Tracking Key in the last line of the code.

```javascript
(function(j,o,u,r,n,e,y){j['CrossEngageObject']=n;
j[n]=j[n]||function(){(j[n].q=j[n].q||[]).push(arguments);};
if(j[n].q)return;e=o.createElement(u);y=o.getElementsByTagName(u)[0];
e.async=!0;e.src=r;y.parentNode.insertBefore(e,y);
})(window,document,'script','https://app.crossengage.io/xng/ce.js','ce');
ce({ apiKey: 'your-api-key' });
```

Paste the code snippet to the \<head> of your website, wrapped in \<script>...\</script>.


# Configuration & Config Commands

#### Configuring the tracking SDK

The tracking SDK can be configured at any time by providing an **object** with the desired settings (see list below). However, some settings like apiKey need to be set as the first command when initialising the SDK.&#x20;

This is why a configuration command with this configuration is already included in the HTML Snippet (or GTM Tag Template) and it can be expanded with additional configurations.

```
// Interface:
ce({
  [configuration property]: [value]
  [configuration property]: [value]
});

// Example:
ce({
  silentLogs: true,
  rootDomain: 'example.com'
});
```

#### Reading the Configuration

The current configuration and its values can also be read by using a **callback command**.\
Note that the configuration can not be changed by manipulating the returned configuration, but must be configured as described above.

To read the current configuration or just insert a custom operation into the **command queue**, you can use a **Callback Command.** These take a function as argument, which will inserted and executed via the **command queue**. The function will be called with an **immutable copy** of the current (at time of execution) configuration.

```
// Interface: 
ce(function(configuration) {
  //...
});

// Example:
ce(function(configuration) {
  console.log(configuration.globalUserId)
});
```

#### Possible Configuration Properties: <a href="#possible-configuration-properties" id="possible-configuration-properties"></a>

| Property                 | value type            | default value                                                                                                                                                                                                            | description                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ------------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `apiKey`                 | *String*              | `-`                                                                                                                                                                                                                      | The Tracking API Key of your company. The first command of the SDK must set this value.                                                                                                                                                                                                                                                                                                                                                                                              |
| `apiUrl`                 | *String*              | <p><a href="https://trk-api.crossengage.io/api/v1"><https://trk-></a></p><p><a href="https://trk-api.crossengage.io/api/v1">api.crossengage.io/</a></p><p><a href="https://trk-api.crossengage.io/api/v1">api/v1</a></p> | The CrossEngage Tracking API to which all tracking requests are being made. Usually this should not be changed.                                                                                                                                                                                                                                                                                                                                                                      |
| `globalEvent Properties` | *Javascript Object*   | `{}`                                                                                                                                                                                                                     | This configuration can be used to add specific properties and values to all tracking events that get passed to the tracking API. The properties will be added to the **properties** part of the payload of the request.                                                                                                                                                                                                                                                              |
| `globalUserId`           | *String*              | `null`                                                                                                                                                                                                                   | <p>The <em>xngGlobalUserId</em> by which the user is tracked globally within the system. If this value is not set, it will be set automatically after the first request to the CrossEngage API, assigning the user this id.</p><p><em>When set, it will add a cookie to the users browser to store this setting and apply it on the next page load.</em></p><p>It is not recommended, but for very specific use cases this value can be manually overwritten as well.</p>            |
| `rootDomain`             | *Boolean* or *String* | `false`                                                                                                                                                                                                                  | As cookies are used to track a user across sessions, these cookies are always set to a specific domain. Usually this is the exact (sub)domain that the tracking SDK has been loaded on. If you want the cookie to be set on a higher domain level or even the root domain, this setting can be used either by providing the exact domain name that the cookie should use or the boolean value **true** to let the SDK identify and use the root domain automatically.                |
| `sessionId`              | *String*              | `null`                                                                                                                                                                                                                   | <p>The <em>sessionId</em> by which the users current session is tracked globally within the system. If this value is not set, it will be set automatically after the first request to the CrossEngage API, assigning the user this id.</p><p><em>When set, it will add a cookie to the users browser to store this setting and apply it on the next page load.</em></p><p>It is not recommended, but for very specific use cases this value can be manually overwritten as well.</p> |
| `silentLogs`             | *Boolean*             | `false`                                                                                                                                                                                                                  | By default, the tracking SDK displays a variety of usable errors and warnings in the developer console of the browser, if required. These errors and warnings can be disabled entirely, allowing only low level Javascript runtime errors to pass.                                                                                                                                                                                                                                   |
| `trackingOptIn`          | *Boolean*             | `false`                                                                                                                                                                                                                  | <p>By default, the tracking SDK will be in a non-tracking mode. It will execute and run all its internal code logic and functions, but will not make any http request to the CrossEngage tracking API. This configuration will allow requests to the API when enabled, which is required for user tracking.<br><em>When true, it will add a cookie to the users browser to store this setting and apply it on the next page load.</em></p>                                           |
| `forceEnablePolling`     | *Boolean*             | `false`                                                                                                                                                                                                                  | By default, polling is disabled if no onsite, exit intent or browser notification integration is enabled. With this config, the polling can be enabled to e.g. allow fixing wrongly merged users.                                                                                                                                                                                                                                                                                    |


# Tracking User Behavior

CrossEngage's web tracking SDK uses an event-based system to track user behaviour. To send these events to CrossEngage, you may use one of the following three methods, depending on the behaviour you would like to track or even set up custom functions & triggers.

To trigger a predefined or a custom event, you can use the **Trigger Command** functionality which is used by providing the trigger name as string and additional arguments based on the trigger:

```
// Interface: 
ce([triggerCommandName], <...[commandParameters]>);

// Example:
ce('identify', {email: 'me@emailprovider.com'});
```

{% hint style="warning" %}
Please note that that **no user tracking will occur** until the configuration `ce({trackingOptIn: true});` has been set.
{% endhint %}


# Identify Method

### Overview <a href="#about-the-method" id="about-the-method"></a>

The `identify` method is used to identify, create and update users in CrossEngage. This means that anytime you can relate user's actions or attributes to a recognizable user ID, you should consider triggering `identify` e.g. when a user logs in, updates their profile or signs up for a newsletter.

You do not need to call `identify` for anonymous visitors of your website as CrossEngage automatically assigns them an anonymous `xngGlobalUserId`.

{% hint style="warning" %}
Personal information can be sent via web tracking but we recommend to transmit sensitive information (like address, telephone etc) per API or upload via feed.
{% endhint %}

The `identify` method has the following structure for updating users based on their `externalId` (default):

```
ce('identify', '123abc');
```

For cases when you may not have access to the `externalId`, CrossEngage allows you to identify users using `email`

```
ce('identify', {email: 'me@emailprovider.com'});
```

{% hint style="info" %}
Please note that CrossEngage automatically fills the businessUnit property with an empty string when it is not provided. This will prevent the duplication of profiles with the same email address which do not have a business unit
{% endhint %}

If you are using business units in your CrossEngage instance, you also need to provide the respective `businessUnit` when identifying users via `email` .

```
var attributes = {
    "email": "john@xng.com",     
    "businessUnit": "DE"
    }; ​

ce('identify', attributes);
```

## Implementation <a href="#implementation" id="implementation"></a>

**id** or **email** (and if used also **businessUnit)** needs to be available in your data layer before you fire the request to us. If not, this might lead to incorrect mapping.

This section goes through the methods that can be used for user identification in cases where an id is known and when it is not.

### Identify users with an id <a href="#identify-users-with-an-id" id="identify-users-with-an-id"></a>

```
ce('identify','12345abcd');
```

1. Copy the snippet.
2. Create a custom HTML tag on your tag manager and paste the snippet.
3. Set up a trigger which fires upon a form submission, or any occasion, the user-identity is exposed.&#x20;

Using the function that listens for the form's submission, call the `identify` function with the `externalId` exposed by your website.&#x20;

### Identifying a user using email <a href="#identifying-a-user-using-email" id="identifying-a-user-using-email"></a>

For cases when you may not have access to the `externalId`, CrossEngage allows you to identify users using `email`. In this case, the `noUserId` property must have as its value `true`. This will indicate to our tracking library that the user id is not known:

```
var attributes = {
    "email": "john@xng.com",     
    "businessUnit": "DE"
    }; ​

ce('identify', attributes);
```


# Update Method

### **Overview** <a href="#about-the-method" id="about-the-method"></a>

The `update` method is used to update user information in CrossEngage. This means that anytime you want to provide/update user attributes based on the information available on the website, you can use this method to update attributes/traits in CrossEngage.

You do not need to identify users to update them via the update method, as CrossEngage automatically assigns them an anonymous `xngGlobalUserId`.

Personal information can of course be sent via web tracking but we recommend to transmit sensitive information (like address, telephone etc) per API or upload via feed.

The `update` method has the following structure for updating users:

```
ce('update', { name: 'Jeff', age: 59 });
```

{% hint style="warning" %}
If the user trait name overlaps with an identifier(e.g. email), it will override that identifier.&#x20;
{% endhint %}

## Use Cases <a href="#about-the-method" id="about-the-method"></a>

#### **A user changes their address information** <a href="#a-user-changes-their-address-information" id="a-user-changes-their-address-information"></a>

Upon form submission, call the `update` function with the new address values:

```
var attributes = {    
    "address": "Bertha-Benz-Strasse 5",    
    "postCode": "10557",     
    "city": "Berlin",    
    "country": "Germany"};
    
ce('update', attributes);
```

This ensures that this user's data is updated on the CrossEngage platform in real time. For example, after an update is made, direct mail campaigns can immediately have access to the most recent address information.

#### **A user signs up using their personal information** <a href="#a-user-signs-up-using-their-personal-information" id="a-user-signs-up-using-their-personal-information"></a>

Upon successful registration, call the `identify` function with the newly created `externalId` followed by an update call containing any newly gathered information:

```
var externalId = "211519787" 
var attributes = {    
    "name": "John Doe",    
    "plan": "tier3" 
    };

ce('identify', externalId);
ce('update', attributes);
```

You should consider sending all of the information that the user provided in their registration form so the user is set up on the CrossEngage platform in real time.

{% hint style="warning" %}
Never send any user passwords or tokens through CrossEngage web tracking functions.
{% endhint %}


# Page Method

### Overview <a href="#about-the-method" id="about-the-method"></a>

The `page` method is used to track page views, creating `Viewed Page` events for users the function is called for. You should only trigger this method upon successful page loads or route changes in the case of single page applications. This method automatically sends gathers and sends information regarding the page, browser session and operating system configuration of tracked users to CrossEngage.

The `page` method has the following structure:

```
ce('track', 'Viewed Page')
```

### Implementation <a href="#implementation" id="implementation"></a>

This page method is not needed on each page - only on those for which a specific use case might arise, e.g. sales-, special offer-, voucher-pages. You can leave out the page method on the product detail pages as the [track method](/data-and-engagement-platform/web-tracking/web-tracking-v2/tracking-user-behavior/track-method) can be used instead.

1. Copy the `page` method snippet.
2. Create a custom HTML tag on your tag manager and paste the snippet between HTML tags.
3. Set up a trigger which fires the tag upon every page load.

Call the method each time you consider a new page is loaded.

If you are setting up the `page` method for a single page application, ensure that you set up the trigger based on routing changes rather than page loads.

### &#x20;Gathered data <a href="#gathered-data" id="gathered-data"></a>

The information the `page` method transmits is stored in a `context` object, which has a syntax similar to the example below:

```
{     
language: "en-US",     
languages: ["en-US", "en", "de"],     
location: "https://www.crossengage.io/TPS-Report/cover/",     
page: {         
    path: "/TPS-Report/cover/",         
    referrer: "https://www.crossengage.io/TPS-Report/",         
    search: "TPS",         
    title: "TPS Report",         
    url: "https://www.crossengage.io/TPS-Report/cover/"     
    },     
platform: "MacIntel",     
siteId: "www.initech.com",     
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1)" 
}
```

## Use cases <a href="#use-cases" id="use-cases"></a>

### Segment users that have **visited the women shoes category of your shop** <a href="#segment-users-that-have-visited-the-women-shoes-category-of-your-shop" id="segment-users-that-have-visited-the-women-shoes-category-of-your-shop"></a>

The below block is an example of a `context` object from a `Viewed Page` event which we will be targeting for this example:

```
{     
language: "en-US",     
languages: ["en-US", "en", "de"],     
location: "https://www.crossengage.io/TPS-Report/cover/",     
page: {         
    path: "/women/shoes/",         
    referrer: "",         
    search: "shoes",         
    title: "Women shoes",        
    url: "https://www.crossengage.io/women/shoes/"     
    }, 
platform: "MacIntel",     
referrer: "",     
siteId: "www.crossengage.io",     
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1)" 
}
```

To segment all users that have visited the women shoes category of your shop, create a segment condition filtering `Viewed Page` events with the property `context.page.path` using the `contains` operator with the value `women/shoes`.

### **Segment users that have visited the FAQ section of your site** <a href="#segment-users-that-have-visited-the-faq-section-of-your-site" id="segment-users-that-have-visited-the-faq-section-of-your-site"></a>

The below block is an example of a `context` object from a `Viewed Page` event which we will be targeting for this example:

```
{     
language: "en-US",     
languages: ["en-US", "en", "de"],     
location: "https://www.crossengage.io/faq/",     
page: {         
    path: "/faq/",         
    referrer: "",         
    search: "frequently asked questions",         
    title: "FAQ",         
    url: "https://www.crossengage.io/faq/"     
    },     
platform: "MacIntel",     
referrer: "",     
siteId: "www.crossengage.io",     
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1)" 
}
```

To segment all users that have visited the FAQ section of your site, create a segment condition filtering `Viewed Page` events with the property `context.page.title` using the `contains` operator with the value `FAQ`.

Depending on the use case you would like to satisfy, you may use any of the properties sent in the context of the **Viewed Page** event or even a combination of them. For example, you may want to segment all users which have visited your FAQ page, redirected from google. To segment these users, create a segment condition filtering `Viewed Page` events with the property `context.page.referrer` using the `contains` operator with the value `google` and the property `context.page.title` using the `contains` operator with the value `faq`.


# Track Method

### Overview <a href="#about-the-method" id="about-the-method"></a>

The `track` method is used to track any user behaviour as event. You may track any behaviour that you would like to use to segment users in CrossEngage to use for campaigns. These can be anything from page views, completing purchases, viewing the cart, adjusting delivery preferences to changing a products' colors in an onsite configurator.

The `track` method has the following structure:

```
ce('track', 'Added Product', { 'sku':'E12371'});
```

#### Method Parameters <a href="#method-parameters" id="method-parameters"></a>

| Value        | Type   | Description                                                           |
| ------------ | ------ | --------------------------------------------------------------------- |
| `eventName`  | string | The name of the event your are sending to CrossEngage.                |
| `attributes` | object | Object that contains information about the event, see examples below. |

### Implementation <a href="#implementation" id="implementation"></a>

#### Standard CrossEngage events <a href="#standard-crossengage-events" id="standard-crossengage-events"></a>

CrossEngage offers a range of predefined events which you can call without requiring any further event definition.

#### Viewed Product <a href="#viewed-product" id="viewed-product"></a>

A user views a specific product on your website:

```
var attributes = {     
    'sku': '46493-32',     
    'name': 'Uno Card Games',     
    'price': 300.00,     
    'currency': 'USD',     
    'category': 'Games' }; 

ce('track','Viewed Product', attributes);
```

#### Added Product / Removed product <a href="#added-product-removed-product" id="added-product-removed-product"></a>

A user adds a product or removes a product from their cart:

```
var attributes = {   
  'sku': '16493-37',     
  'name': 'Uno Card Games',    
  'price': 300.00,     
  'currency': 'USD',     
  'category': 'Games' ,    
  'cart': {        
    'products': [            
      {                
      'sku': '45790-32',                 
      'price': 200,                 
      'name': 'Monopoly 3rd Edition',                 
      'category': 'Games',                 
      'currency': 'USD'            
      },             
      {              
      'sku': '65112-30',                 
      'price': 149.99,                
       'name': 'Catan',                
      'category': 'Games',                 
      'currency': 'USD'            
      }        
    ]    
  }};
  
ce('track','Added Product', attributes);
ce('track','Removed Product', attributes);
```

For **all product-related events** containing the cart object, the full current state of the cart should be passed, as the information in CrossEngage will be overwritten with each such event. The `cart` object itself is not customisable, meaning no custom attributes (like `cart.cartId`) can be added. Custom attributes can be added on the event's root level.

In addition, the`sku` of the respective product should be provided on the top (root) level of the event data for all product-related events. This allows using this data with Product Feed events (Product Back/Low In Stock, Product Price Increased/Reduced) in real-time campaigns.

#### Searched Products <a href="#searched-products" id="searched-products"></a>

A user uses a search bar to look for products on your shop:

```
var attributes = {  
    'searchTerm': 'board games',  
    'productsDisplayed': 10
    };

ce('track','Searched Products', attributes);
```

#### **Completed Order** <a href="#completed-order" id="completed-order"></a>

A user completes a purchase.

For each product in the `products` array, CrossEngage will trigger an additional event named`Ordered Item`. This event can be used to easily segment users that have purchased a particular item.

Note that `sku` is mandatory for each product in the `products` array.

```
var attributes = {  
    'orderId': '50314b8e9bcf000000000000',  
    'total': 47.68,  
    'shipping': 4.5,  
    'tax': 19,  
    'discount': 5,  
    'coupon': 'hasbros',  
    'currency': 'USD',  
    'cart': {    
        'total': 40.49,    
        'currency': 'EUR',    
        'products': [        
            {          
            'sku': '45790-32',          
            'name': 'Monopoly: 3rd Edition',          
            'price': 29.50,          
            'quantity': 1,          
            'category': 'Games'        
            },{          
            'sku': '46493-32',          
            'name': 'Uno Card Game',          
            'price': 10.99,          
            'quantity': 2,          
            'category': 'Games'        
            }]  
        }};

ce('track','Completed Order', attributes);
```

Sending **Completed Order** via Feed is recommended for historical event. Once your historical orders have been added to our system, **Completed Order** event is mostly done via API.

#### **Viewed Cart** <a href="#viewed-cart" id="viewed-cart"></a>

A user views their cart anywhere on your site. You can trigger this either on loading the full cart page or even a cart overlay that is triggered from the navigation bar.

```
var attributes = {  
    'cart': {    
        'total': 40,    
        'currency': 'EUR',    
        'products': [			
            {			  
            'sku': '12351920', 			  
            'name': 'Stiletto Shoes', 			 
            'price': 20, 			  
            'quantity': 2			
            }]  
        }};
ce('track','Viewed Cart', attributes);
```

### Sending custom events <a href="#sending-custom-events" id="sending-custom-events"></a>

The CrossEngage web tracking library allows you to also send custom events through the `track` method. To send custom events, please contact your dedicated Customer Success manager so that they can define these events and their properties for use within the CrossEngage platform.

To make it easier for us to prepare the events for you, please send your Customer Success manager the structure of the event in the following format:

```
{
'Custom Event Name': 
    {        
    'property 1 name': string,        
    'property 2 name': boolean
    }
}
```

The formats supported by CrossEngage are the following:

* `string`
* `integer`
* `float`
* `datetime`
* `array`
* `object`

## Use cases <a href="#use-cases" id="use-cases"></a>

**A user makes a purchase**

Using the `Completed Order` predefined CrossEngage event structure, call the `track` method with the entire cart object, including all products in the cart at the time of purchase.

When a `Completed Order` event is sent to CrossEngage, it will automatically trigger an `Ordered Item` event for each of the products in the cart to allow you to easily segment users ordering particular products of a specific category or a within a specific price range.

To segment all users that have completed orders, create a segment condition filtering `Completed Order` events. You may also use the event property `cart.total` with the operator `greater than` to additionally segment users that have completed an order over a given value.

**A user views a cart overlay from the navbar of your site.**

Using the `Viewed Cart` predefined CrossEngage event structure, call the `track` method with the entire cart object.

It is recommended that you send all products in the cart and all available product information to ensure that you gather all relevant data for segmentation purposes.

To segment all users that have viewed their cart, create a segment condition filtering `Viewed Cart` events. You may also use the event property `cart.total` with the operator `greater than` to additionally segment only users viewing carts over a given amount.

**A user changes the color of a shoe in an onsite configurator.**

Contact your dedicated Customer Success manager and define a custom event called, for example, `Colour Changed` with a structure as per below:

```
{    
'Colour Changed': 
    {        
    'colour': string,        
    'category': string,        
    'shoeSize': integer,        
    'imageUrl': string    
    }
}
```

Once receiving confirmation that the event is ready for use, you may now call the `track` method with a payload similar to the one below:

```
var attributes = {  
    'colour': 'red',  
    'category': 'shoes',  
    'shoeSize': 36,  
    'imageUrl': 'https://www.crossengage.io/images/catalog/product/stiletto.jpg'
    };
ce('track','Colour Changed', attributes);
```

To segment all users that have changed their shoe color in an online configurator, create a segment condition filtering `Colour Changed` events with the property `category` using the `equals` operator with the value `shoes`.

Consider sending all the information that is relevant as this may be used for message personalization.


# Opt-Out from Tracking

To ensure user privacy is handled correctly, the Tracking SDK (v2) will opt out from tracking by default and tracking opt in must be enabled via the configuration to enable tracking like this:&#x20;

```
ce({trackingOptIn: true});
```

By default, the tracking SDK will be in a non-tracking mode. It will execute and run all its internal code logic and functions, but will not make any http request to the CrossEngage tracking API. This configuration will allow requests to the API when enabled, which is required for user tracking.\
When true, it will add a cookie to the users browser to store this setting and apply it on the next page load.

To set a opt-out cookie for a given user and stop the CrossEngage tracking library from sending API-request to the CrossEngage Web-tracking API, you can simply set to tracking opt-out to false:

```
ce({trackingOptIn: false});
```


# Testing & Debugging

How to debug tracking SDK

#### Setting up the Debug Panel

After setting up the web tracking SDK, the best way to debug it is by going on the site it was installed on and setting the following config, by using the browser console:

```
ce.enableDebug(true)
```

This will set a temporary local cookie( expiring after 7 days), that enables the CrossEngage Debug Console, which will be visible after a hard refresh of that website in the bottom right corner. Please note that this configuration will only affect your own browser in which this cookie is set.&#x20;

You can then access the debug panel by simply clicking on the shown panel.&#x20;

<figure><img src="/files/uCad6Z7MD6VUVZsyF1WA" alt=""><figcaption></figcaption></figure>

We also always automatically show all executed tracking calls.&#x20;

#### Using the Debug Panel

You can use the debug Panel to:&#x20;

* Access/View the current **SDK configuration**
* **Monitor the triggered Events** and have a detailed view of the event payloads, responses as well as the order in which the events have been sent
* **Trigger Events and User updates -** allowing you to quickly test and also imitate user behaviour


# Migrate Tracking SDK v1 -> v2

This section is aimed to touch on the most important topics related to migrating from our old tracking SDK to the new SDK. If there are any questions/uncertainties in the process of migration, please [reach out to the CrossEngage support](/data-and-engagement-platform/help-and-support/reach-out-to-customer-support).&#x20;

### Tracking SDK Setup

Exchange the HTML snippet loading the tracking SDK with our tracking template or with the updated HTML snippet visible in the System Setup section of your CrossEngage instance and apply the same trigger logic as previously used.

Please read the [setup ](/data-and-engagement-platform/web-tracking/web-tracking-v2)section of our documentation for information around using the GTM-Template as well as further information on additional options and configurations.

{% hint style="warning" %}
The new Tracking SDK **opts any user out** from tracking by default. This means that no user tracking will occur until the configuration `ce({trackingOptIn: true})`; has been set.
{% endhint %}

### Tracking, Identify and Updating Users

Formats and payloads of the tracking data has not changed. Only the API to provide these is slightly differen&#x74;**.**&#x20;

Please make sure to visit all your tags triggering updates to CrossEngage and change the tags according to the documentation below.&#x20;

{% hint style="info" %}
Because **identifying** and **updating** are now separated, you might need to split a previous `analytics.identify` where both was done in one API call. In that case, just send the **update** with the attributes after the **identify.**
{% endhint %}

| Tracking SDK v1 (Legacy)                                                                                                                   | Tracking SDK v2                                                                                                                      |
| ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| <p>Viewed Page tracking event </p><p></p><p><code>analytics.page();</code></p>                                                             | <p>Viewed Page tracking event </p><p></p><p><code>ce('track', 'Viewed Page');</code></p>                                             |
| <p>Any tracking event (default or custom) </p><p></p><p><code>analytics.track('Added Product', {properties});</code></p>                   | <p>Any tracking event (default or custom) </p><p></p><p><code>ce('track', 'Added Product', {properties});</code></p>                 |
| <p>Identify a user by externalId</p><p></p><p><code>analytics.identify('123-456');</code></p>                                              | <p>Identify a user by externalId</p><p></p><p><code>ce('identify', '123-456');</code></p>                                            |
| <p>Identify a user by email</p><p></p><p><code>analytics.identify({ email: '<test@test.com>' });</code></p>                                | <p>Identify a user by email</p><p></p><p><code>ce('identify', { email: '<test@test.com>' });</code></p>                              |
| <p>Setting or updating user attributes</p><p></p><p><code>analytics.identify({ name: 'Peter Smith', age: 59, city: 'Berlin' });</code></p> | <p>Setting or updating user attributes</p><p></p><p><code>ce('update', { name: 'Peter Smith', age: 59, city: 'Berlin' });</code></p> |

### Additional options

You might have used a global additionalOptions variable to make sure that certain properties always get added to the event payload of every tracking event.

In the new tracking SDK this functionality can be recreated by configuring it with globalEventProperties(see **Configuration & Config Commands**).\
In the new tracking SDK this configuration is readable and can be set and updated at any time.

All properties within globalEventProperties will get added to the properties property of any track, identify or update event call.

{% hint style="warning" %}
When migrating this to the new SDK, make sure your additional properties are nested in the correct and desired way as they were before.
{% endhint %}

### Accessing the xngGlobalUserId and xngSessionId

To provide a safer and more future proof way to maintain cookies and other forms of persistent storage, we strongly recommend to **never** read or write any cookies or other CrossEngage related storage values directly.&#x20;

Instead the **xngGlobalUserId** and **xngSessionId** can be read and set as part of the configuration (see [**Configuration & Config Commands**](broken://pages/-MMk8R-1UrUHjitkG4Xu)) if needed.\
We have also changed and update various cookie names and references. Old cookies will be converted and deleted when the new tracking SDK detects them.

| Tracking SDK v1 (Legacy) | Tracking SDK v2    |
| ------------------------ | ------------------ |
| xng.gid                  | ce.guid            |
| xng.sid                  | ce.sid             |
| xng.tracking-opt-out     | ce.tracking-opt-in |

### Tracking Opt-Out

The old tracking library provided multiple methods to set the tracking optIn/OptOut status, like\
xng.setTrackingOptOut() etc. and other methods to check the opt out status.

To ensure user privacy is handled correctly, the new tracking SDK will opt out from tracking by default and tracking opt in must be enabled via the configuration to enable tracking like this:\
ce({trackingOptIn: true});\
\
As the tracking optIn status is now a configuration, it can be set and read as described in [Configuration](/data-and-engagement-platform/web-tracking/web-tracking-v2/configuration-and-config-commands).


# Mobile Web Tracking

Mobile tracking is a variation of the usual web tracking, but it isn’t tracking user behaviour (viewed pages, orders etc.) and other user updates via a webbrowser with the help of a cookie to continuously identify users.

Instead a separate mobile id (e.g. app id) gets assigned to a user profile, which is then used for any future updates to the user. These mobile ids must be unique, but a user can have multiple active mobile ids that could connect different apps or other sources to the user profile.

### Tracking Methods

There are two methods, “identify” and “track”, similar to the regular web tracking. Both have a slightly different API endpoint, which includes the Mobile tracking API key which can be found in the [System Setup](https://app.crossengage.io/settings/system-setup).

#### Identify

The main purpose of “identify” is to assign the mobile Id of a user to an already existing user profile (or lead). In order to do that, either the external Id or the combination of email and businessUnit must be known, since these are the unique identifier in the Crossengage system.

Additionally its also possible to update user traits with this method.

**API endpoint**

`POST /api/v1/mobile/{mobileApiKey}/identify`

**Headers**

`Content-Type: application/json`&#x20;

**Parameter list in the payload**

| Parameter    | Required   | Info                         |
| ------------ | ---------- | ---------------------------- |
| mobileId     | Required   | mobile id of customer        |
| userId       | Optional\* | external user id of customer |
| email        | Optional\* | email of customer            |
| businessUnit | Optional\* | business unit of customer    |
| type         | Required   | send as "identify"           |
| timestamp    | Automatic  | now                          |
| traits       | Optional   | traits of customer           |

{% hint style="info" %}
\*Either userId (=external Id) or email+businessUnit must be provided in every “identify”-call.
{% endhint %}

**Example payload**

```
{
	"userId": "ext123456",
	"mobileId": "mob123456",
	"type": "identify",
	"traits": {
		"firstName": "Brad",
		"lastName": "Pitt",
		"language": "en"
	}
}
```

```
{
	"email": "ext123456@example.com",
	"businessUnit":"test",
	"mobileId": "mob123456",
	"type": "identify",
	"traits": {
		"firstName": "Brad",
		"lastName": "Pitt",
		"language": "en"
	}
}
```

#### Track

“Track” is the method to send events to the system, which uses the previously assigned mobile Id as the identifier. It is possible to send any event, similar to the regular API.

**API endpoint**

`POST /api/v1/mobile/{mobileApiKey}/track`

**Headers**

`Content-Type: application/json`&#x20;

**Parameter list in the payload**

| Parameter  | Required  | Info                    |
| ---------- | --------- | ----------------------- |
| mobileId   | Required  | mobile id of customer   |
| type       | Required  | send as "track"         |
| event      | Required  | event name              |
| properties | Optional  | properties of the event |
| timestamp  | Automatic | now                     |

**Example payload**

```
{
	"mobileId": "mob123456",
	"type": "track",
	"event": "Completed Order",
	"properties": {
		"cart": {
			"total": 0,
			"currency": "EUR",
			"products": [
				{
					"id": "507f1f77bcf86cd879439023",
					"sku": "61979589",
					"name": "Zegna Shirt",
					"price": 150,
					"quantity": 1,
					"category": "Shirts",
					"hasZipper": false
				},
				{
					"id": "507f1f77bcf86cd799439011",
					"sku": "51979501",
					"name": "Levi Jeans",
					"price": 100,
					"quantity": 1,
					"category": "Jeans",
					"hasZipper": true
				}
			]
		}
	}
}
```

```
{
	"mobileId": "mob123456",
	"type": "track",
	"event": "Viewed Page",
	"properties": {
		"url":"www.example.com"
	}
}
```

#### Update User-Traits (with and without "Identify"-call)

The mobile tracking API does not have an "Update"-method like the regular web tracking to update user-traits, but user trait can be updated with both the "Identify"- and the "Track"-method.&#x20;

Example "track":

```
{
	"mobileId": "mob123456",
	"type": "track",
	"event": "Viewed Page",
	"properties": {
		"url":"www.example.com"
	},
	"traits": {
		"language": "de"
	}
}
```

#### Anonymous Tracking

Its not mandatory to identify users before tracking can happen. If a mobile Id used by the “track”-method is not yet assigned to an existing user, its still possible to track the events. Similar to a not identified regular web tracking user, the system will create a new user profile as an anonymous user.

If at any time later this mobile id is used in an “identify”-call, then this anonymous user will get merged into the already existing user (or updated with the external Id if no user with that id exists yet).

### Known issues

#### Re-assigning mobile Ids

There is no functionality that prevents assigning a mobile Id to a new user. In this case the mobile Id simply gets removed from the old user and added to the new one. Any previously merged events and traits remain in the old user and don’t get moved with the id.

#### API calls too fast

Example: If a user gets identified and a track call for the same mobile Id gets sent too fast or even at the same time, this could in some rare cases result in duplicated users/multiple users with the same mobile Id.

It is recommended to have at least a few hundred ms between calls.


# User Segmentation

CrossEngage enables you to create user segments, based on User Traits or User Behavior. This allows you, not only to better understand your User Base, but also to tailor your communications for specific User Groups, across a number of channels.

Note that Segments are re-calculated every time they are used. This ensures that you always see the most up-to-date information on your segments, and ensures that new Users, added after a Segment was created, will be automatically added to a segment under use, if they fit the Criteria for it.


# Creating a Segment

* To create a new User Segment, go to **User Segments** and click on **Create New Segment**.

<figure><img src="/files/xOoI6Yj0hy9Xs9N5tZ4q" alt=""><figcaption><p>Creating a new User Segment</p></figcaption></figure>

* Give your Segment a meaningful name.
* Optionally, you can add a Label to your Segment. Labels can help you organize your Users Segments, especially if you expect to create a large number of them.
* Optionally, you can drag and drop the **Segment Block** from the sidebar on the left in the Segment Area. This allows you to create a [Sub-Segment](/data-and-engagement-platform/user-segmentation/combining-segments). Click on the Segment Block, and choose a Segment.
* Drag and Drop the **Condition Blocks** from the sidebar on the left. Click on each Condition Block and choose a Condition.
* Additionally, you can drop a Condition on top of another Condition, to create a **Group**.
  * A group set to **AND** requires a User to meet all Conditions in it, to be added to the Segment.
  * A group set to **OR** requires a User to meet atleast 1 Condition, to be added to the Segment.

<figure><img src="/files/espnDzXjtAHMBZiYaIVE" alt=""><figcaption><p>A Segment of Users, age 18 to 25</p></figcaption></figure>

* Click on **Save Changes**.

You can create Segments using User Attribute Conditions, and Event Conditions. In simple terms, we can say that User Attribute Condition creates Segments using *who a User is*, while the Event Condition creates Segments using *what a User does*.


# Conditions

### User Attribute Condition

The User Attribute Condition uses information from the User Profiles and online shopping cart to segment users. The traits in a User Profile, such as age, gender, or contact information, are largely static; They do not change with time. Hence a Segment built with such a User Attribute Conditions is not likely to change, except when new Users are added to the User Database.

### Event Condition

The Event Condition uses information from Events, such as Onsite User Activity or User Interaction with sent Messages. The Event Condition depends on the Behavior of the User - hence it can be hard to predict how many Users will enter a given Segment, as these Events will continue to take place in the future. It can be paired with other Conditions to restrict the Segment to certain demographics.

{% hint style="info" %}
You can also specify custom events based on your business needs and send them via API. Please[ submit a request](https://crossengage.atlassian.net/servicedesk/customer/portal/2) to Customer Experience team for the creation of the events you would like to send and add their exact names.
{% endhint %}

When a User is sent a Message via a CrossEngage Channel, this generates Events that show the User's interaction with the Message. For example, we can Segment Users based on if they received or opened an email, or if they click a web notification.

### Segmentation based on a past Campaign

In order to see who received a message in a specific campaign, you need to build a segment that targets the recipients of that campaign. Should you only want to check the campaign performance, please go to the campaign dashboard. You will need the following information to access the list of users:

* **ID of the campaign**\
  The campaign ID can be found next to campaign name in the campaign overview or in the list of campaigns
* **Channel or provider used to send the message**\
  The Channel and Provider can be seen from the Messages Section of the Campaign.


# Combining Segments

Segment inclusion simplifies the way you create segments in CrossEngage by allowing you to reuse existing conditions and build on top of them. You can include segments with broader characteristics as a default audience and use it as a baseline. You can then drill down on this default audience by adding further characteristics that are important for user targeting.

If used properly, combining multiple segments can help create complex User Segments that are still easy to comprehend and use.

### Segment Overlap

By combining multiple existing segments, you can reach users that belong to all of the added segments.

<figure><img src="/files/NA6GXHOkNrfgJ0P5nffS" alt=""><figcaption><p>Capturing the Overlap between two User Segments</p></figcaption></figure>

Example Use Case: Optimization of RFM segment building (add link)

### Targeted Exclusion of Users

By adding a Segment and some Conditions, you can exclude Users who have not performed a certain activity or who do not possess certain characteristics.

<figure><img src="/files/t8vpedQ0WoecasGOgZl2" alt=""><figcaption><p>Capturing Users from Segment 1, who have NOT performed some Activity</p></figcaption></figure>

Depending on available data, you can implement this in several different ways:

* **True/False fields**: Data fields of boolean type allow you to select whether the entered value applies to a user (“true”) or not (“false”). Choose “false” if you want specific user information to be excluded.\
  Example: `traits.activeCustomer equals false`
* **Status fields**: Your customers and their orders may be assigned to certain statuses. Providing “active” and “inactive” options is one of the most common examples. Should you, for example, want to target inactive customers, select the “inactive” status in the segment condition.\
  Example: `traits.status equals inactive`
* **Exclusion of available options**: Find out what available values you can use and define those you are not looking for by selecting the “unequals” operator in the segment condition. For example, if you’d like to reach all customers that live outside of Berlin, build a segment where the value for a user’s city does not equal “Berlin”.\
  Example: `traits.city unequals Berlin`&#x20;
* **Event history**: Should you want to target users who have not reacted to a message or visited your website in a while, set the number of occurrences for this event to “0” and choose a specific timeframe if needed.\
  Example: `Completed Order equals 0`


# Messages

The CrossEngage Data & Engagement Platform offers a variety of Channels to send messages to your customers. These can be in the form of SMS or Emails, printed materials or online notifications.

To power many of these these channels, we partner with our Third Party Integration providers. You can find more about these Channels in the [Integrations ](/data-and-engagement-platform/messages/integrations)section.


# Frequency Capping

CrossEngage allows you to set a maximum frequency of messages sent per User in a given time frame. Once this limit is reached, the User does not receive any more messages for the specified duration.

### Setting Global Frequency Cappings

* To set Global Frequency Cappings, go to **More -> Frequency Cappings**.

<figure><img src="/files/G9J9vuGlEx26FsnDUKVM" alt=""><figcaption></figcaption></figure>

* Click on **Edit**.
* Here, you can set the total maximum number of messages sent per minute, hour, 1 day (24 hours), 7 days or 30 days.
* You can also set the maximum number of messages for each channel such as email or web notifications.
* Click **Save**.

Frequency capping works in capping intervals and applies to the actual delivery times. The values you define impact each user separately within the target group of your campaign.

For example, if frequency capping is set for "once per day", each user who received a message will not receive any further messages for 1 day.

{% hint style="warning" %}
"Day" is defined as a period of 24 hours, starting from the dispatch of the first message. If an email is sent to the customer at 9am on 1st of January, they will not receive any more emails until 9am on 2nd of January, for a frequency of "once per day".
{% endhint %}

### Campaign Frequency Cappings

Apart from the Global Frequency Cappings, you can also set Cappings in each Campaign to prevent duplication of messages. In such a case, messages are paused for that specific campaign if the Campaign Capping Frequency is reached, and for all Campaigns if the Global Capping Frequency is reached.


# Templates

Templates are a powerful tool in CrossEngage, which allows you to create Message Templates with Hypertext (Text, hyperlinks and digital media such as videos), and re-use them any number of times. Furthermore, by incorporating [Handlebars](/data-and-engagement-platform/messages/personalization) in your Templates, you can customize each message with Specific information about the receipient User.

You can create Templates in CrossEngage using the built-in Template Builder, or by directly using HTML code. You can also use many of the Templates of our Integration Providers. For more information, please refer to the [Integrations](broken://pages/UsQSZuVVJHPDAqOnTPX6) Section.

### Layout of a Template

In CrossEngage, a Template contains parallel horizontal Structures that can be added or removed to change the length of the email. Each Structure contains one or more Containers. These Containers contain the contents of the email, such as Text, Images, Videos and more. By diving the Templates in Structures and Containers, we can easily set up and modify the Template. This also gives us the power to modify parts of the Template as independant units.

Structures are also grouped together as 'Stripes'. Generally, you can combine your Structures in three Stripes - Header, Content and Footer, but you are free to create more stripes as needed.

<figure><img src="/files/bQ1NJE9Np3wRmHuYFDJh" alt=""><figcaption><p>Layout of a Template</p></figcaption></figure>


# Template Builder

* To build a new Template in CrossEngage, go to **More -> Templates**.
* Click on **Create Template** in the Upper Right corner.

<figure><img src="/files/kS7cZDVJc2iwMhz4ZCbb" alt=""><figcaption><p>Creating a new CrossEngage Template</p></figcaption></figure>

* Give your Template a meaningful name.
* Click on the **Appearance Settings** Tab in the sidebar on the left. Set the [Appearance Settings ](#appearance-settings)as needed.
* Click on **Content** Tab in the sidebar on the left. Set the [Content ](#content-settings)of the Template as needed.
* Click **Save**.

### Appearance Settings

The Appearance Settings determine the general style and format of the email, irrespective of the content. The Appearance Settings consist of 5 Sections:

* The **General Settings** contains options such as the Width and Padding of the email (in pixels, px), Fonts, Line Spacing and Background. Any settings here are applied to the entire Template.

{% hint style="warning" %}
The Template has a default width of 600px. You can have any width between 320px and 900px.
{% endhint %}

* **Stripes** provide Font and Background options, similar to General Settings. However, these settings are only applied to the relevent 'Stripe': Header, Content, Footer or the Info Area.
* **Headings** provides the format of Headings in a Template. This supercedes other formattings - Headings will follow this format irrespective of Stripe and General Settings.
* **Button** provides the appearance and behavior of Buttons in the Template.
* **Mobile Formatting** provides Appearance Settings, when the email is viewed on a Mobile Device. This allows you to create Templates that are just as readable and pleasing on Mobile devices, as devices with larger displays.

### Content Settings

After you have set your Appearance Settings, we can start adding Content to the Template.

* The first step in Content is to set the **Structure** of your Template. You can do that from the **Content** tab, or directly from the work area.
  * To add a new Stripe, Hover your pointer on any Stripe, and then Click the Plus ( + ) sign below it.
  * To delete a Stripe, hover your pointer on the Stripe it until you see the **Stripe Options**. Click on 'delete' to remove the Stripe from your Template.
  * To add more Structures, go to **Content -> Structures**. Click and Drag the Structure you want to add. When you Hover it on a Stripe, it will show you the Stripe boundary. Drop the Structure to add it to the Stripe.
  * Alternately, you can Hover on any Structure until you see its **Structure Options.** Click on the "copy" button to create a duplicate of the Structure.
  * To delete a Structure, hover your mouse on it until you see the **Structure Options**. Click on 'delete' to remove the Structure from the Template.
  * Click on any Stripe or Structure. You can now see **Structure Settings** for the Stripe / Structure in the Siderbar on the left. Configure the Stripe / Structure as needed.

{% hint style="info" %}
You can see Options for a Stripe / Structure when you hover on it. You can see Settings of a Stripe / Structure in the left Siderbar when you click on it.
{% endhint %}

<figure><img src="/files/coq42Au5oMFwtG0YsN1l" alt=""><figcaption><p>Options and Settings for Stripes and Structures</p></figcaption></figure>

* After the Layout of your Template is ready, it is time to fill the **Blocks** with Content.
  * Go to **Content -> Blocks**.
  * Drag and Drop the desired kind of Block on any of the Containers on the right. This tells the Template what kind of Content to expect, such as Text, Images, Buttons etc.
  * You can also drop multiple Blocks in a single container. While sometimes useful, this should be done carefully to avoid clutter.
  * Click on the Block to view its **Block Settings** in the left Sidebar. Provide the Content for the Block, such as a URL for Image / Video block or Text for Text Block. Configure the Container / Block as needed.
* **Merge tags:** You can easily select and insert user attributes to personalize your emails using the "Merge tags" drop-down. The handlebar syntax for the selected attribute is inserted where needed. To insert merge tags, go to the text formatting panel in the "Text" basic block and click on the "Merge tags" button.

<figure><img src="/files/7au9rnn32uQoa1HIqN0W" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
You can see Options for a Container / Block when you hover on it. You can see Settings of a Container / Block in the left Siderbar when you click on it.
{% endhint %}

<figure><img src="/files/08VDMZBPoRNC87aOh013" alt=""><figcaption></figcaption></figure>

* The last Section under Content is **Modules**. A module is any Container, Structure or Stripe (not Block) that can be saved for use across all Templates. For example, you can create a Footer Stripe with the option to Unsubscribe / Opt Out of emails, and re-use this Stripe as the Footer for all your Templates.
  * To add a Container / Structure / Stripe as a Module, Hover your mouse pointer over it. Next, Click on the **Save as Module** button in its Options.
  * To edit / delete a Module, go to **Content -> Modules**. Find the required Module. Click on the three dots that appear when you hover your mouse over it. Click on **Edit** / **Delete**.&#x20;

<figure><img src="/files/KYFJJqviYOe6ZshdlRvW" alt=""><figcaption><p>Edit or Delete a Saved Module</p></figcaption></figure>

* **Synchronized models:** Synchronized modules enable you to update your modules across templates. You can enable or disable synchronization of changes per module.
  * Enabling synchronized modules: When saving a block as a module, the option to synchronize the module is shown in the options.

<figure><img src="/files/JX6cXocriDnmcThTTihi" alt="" width="375"><figcaption></figcaption></figure>

* Synchronizing the changes made: The synchronization is ‘off’ by default.

<figure><img src="/files/HO0Iv7GRZ9NQFk5WRhHF" alt="" width="375"><figcaption></figcaption></figure>

* Once you make changes in a synchronized module you can choose to either update this module in all the templates, or update only in the current template, or restore to the original version of the module.

<figure><img src="/files/R3mr9c802P76PZuaBSBl" alt="" width="375"><figcaption></figcaption></figure>

### General Tools

CrossEngage provides 5 additional options in the Top Bar. These are as Follows:

* The **Fonts** button allows you manage fonts not present in the CrossEngage platform by default. Click this button to add or remove Custom Fonts.
* The **Code Editor** button allows you to see the HTML code behind the Template. Click this button once to show the Code Editor; Click it again to hide the Code Editor. While the Code Editor is open, click on any part of the Template to view and edit the code of that specific part.
* The **Preview** button generates a sample Preview of the Template, to show you how it would appear in an email.
* The **Undo** button can be used to Undo last action.
* The **Redo** button can be used to Redo an action after an Undo.&#x20;


# Integrations

Integrations allow the CrossEngage Data & Engagement Platform to connect with third party applications you may use to send messages to your customers.


# Channels


# SMS


# Twilio


# Set up a Twilio Account

Before you begin, you will need the following:

* Paid Twilio Account with an associated phone number (Trial accounts are not supported)
* CrossEngage Account
* User data that includes a phone number

## Buying a Number

{% hint style="warning" %}
The following is an example of how to buy a number. If you want to be sure that you do this correctly, contact Twilio or your account manager for support.
{% endhint %}

You need to have at least one phone number associated with Twilio to use your Twilio account with CrossEngage. To buy a number, follow the steps below:

* [Log in](https://www.twilio.com/login) to your Twilio account.
* In the Account Info section, click on View all Numbers.

<figure><img src="/files/KM64nHa0U2OIig72hTS0" alt=""><figcaption></figcaption></figure>

* You can buy a number from Twilio by clicking on the Buy a Number button and choosing a number to buy.

<figure><img src="/files/qa5fcsu4LuboAVA6fyIP" alt=""><figcaption></figcaption></figure>

### Enable Certificate Validation

We recommend enabling certificate validation as it serves as an additional security measure. Have a look at the [Security Update On SSL Certificate Validation](https://www.twilio.com/blog/2016/02/security-update-on-ssl-certificate-validation.html) blog post to learn more.

To enable SSL Certificate Validation, follow the steps below:

* [Log in](https://www.twilio.com/login) to your Twilio account.
* In the top right corner of the screen, open the Account menu and choose General Settings.
* In the "General settings" section, scroll down to the "SSL Certificate Validation" heading and click `ENABLED`.&#x20;

<figure><img src="/files/jzTGp8Vqm8t8U8emL4lW" alt=""><figcaption></figcaption></figure>

### Configure user attributes

We suggest you to use the "traits.phone" user attribute when using Twilio. The user attribute should include a phone number formatted according to the E.164 specification. For example: +4917612345678. [This Twilio article](https://support.twilio.com/hc/en-us/articles/223183008-Formatting-International-Phone-Numbers) about formatting international phone numbers goes into more detail.


# Set up Twilio Integration

## Fetching Your Twilio API Credentials

Your Twilio API credentials allow CrossEngage to connect to your Twilio account. Once connected, you will be able to send Twilio messages from your CrossEngage account.

* [Log in](https://www.twilio.com/login) to your Twilio account.
* In the top right corner of the screen, open the Account menu and choose General Settings.
* From the Menu on the left, choose API Keys & Tokens.
* Your Account SID and Primary Token (which you can make visible by clicking on the eye icon) can be found here. Leave the tab open as you will need to copy and paste these credentials for your CrossEngage integration in a later step.

<figure><img src="/files/7t3pi525E2OT4uaGTUsY" alt=""><figcaption></figcaption></figure>

## Configuring a Twilio Integration in CrossEngage

* In the CrossEngage app, navigate to `Settings` > `Integrations`.
* Click the `Add new integration` button in the top right corner of the page.

<figure><img src="/files/zfWLFaM1kVBGbSAJoguR" alt=""><figcaption></figcaption></figure>

* Search for Twilio, then click `Set Up`.

<figure><img src="/files/qffqLebQXvLjN8cCvTrH" alt=""><figcaption></figcaption></figure>

## The "SMS via Twilio" form <a href="#the-sms-via-twilio-form" id="the-sms-via-twilio-form"></a>

* Give the integration a descriptive name.
* Copy your Account SID from the Twilio tab you have open and paste it into the Account SID field.
* Copy your Primary Token from the Twilio tab you have open and paste it into the API key field.
* Click `Connect`.

<figure><img src="/files/zlJhhXUDCvpTsizf89Hx" alt=""><figcaption></figcaption></figure>

* Choose the user attribute that contains your recipient's phone number.

{% hint style="info" %}
The traits.phone user attribute is a string type attribute created by default in CrossEngage. That means that if you haven not made your own custom user attribute with the same function, the default attribute "traits.phone" will be the user attribute that contains your recipient's phone number.‌
{% endhint %}

* When ready, click `Apply` to save the integration.

<figure><img src="/files/zlJhhXUDCvpTsizf89Hx" alt=""><figcaption></figcaption></figure>


# Create a Campaign Message

* Log in to your CrossEngage account.
* Go to `Campaigns` and click `Create new campaign` in the top right corner of the page.

<figure><img src="/files/DvQlgHZCTkPXaSHxJwDz" alt=""><figcaption></figcaption></figure>

* Choose whether you want to create an Audience or a Realtime campaign. Information about the distinction between these types of campaigns found [here](/data-and-engagement-platform/campaign-management/campaigns).
* Once you have created your campaign and filled in the “Campaign setup” and “Target group” sections, go to the `Messages` section and click `Create new message`.
* Select `SMS` from the dropdown menu. The message setup screen will open.

<figure><img src="/files/1EZ5W4eyCi7xyHhDMI4A" alt=""><figcaption></figcaption></figure>

* Under the “Send via integration” heading, select the Twilio integration that you set up earlier.

<figure><img src="/files/zCd5eJ26cvg4E84yzbu5" alt=""><figcaption></figcaption></figure>

### Delivery Options <a href="#delivery-options" id="delivery-options"></a>

#### Sender number <a href="#from-number" id="from-number"></a>

* From the dropdown, select one of the numbers you have configured on Twilio.

  This number will be used to send the SMS messages.

#### Message text  <a href="#message-text" id="message-text"></a>

* Write the body of the SMS that you will send. The content can be customised using Handlebars. The [Handlebars ](/data-and-engagement-platform/messages/personalization)page goes into more depth about how you can take advantage of Handlebars.

#### Max price (optional)  <a href="#max-price-optional" id="max-price-optional"></a>

* Write the maximum cost per SMS that you would accept to operate with. Learn more on Twilio's [blog post about Max Price](https://www.twilio.com/blog/2015/08/introducing-max-price.html).

<figure><img src="/files/pQGCTgAkKhIpnul1Yg3L" alt=""><figcaption></figcaption></figure>


# Link Mobility


# Set Up Link Mobility Account

Before you begin, you will need:

* A paid LinkMobility **SMPP** Account.

{% hint style="info" %}
This is **not** the same as your REST API Account. SMPP is a protocol used to send SMS.
{% endhint %}

* Change each LinkMobility account's parallel connection allowance to 10 (the default setting is one). This is so that CrossEngage can run multiple nodes for load balancing.
* Account rate limits of at least 100 requests/second.
* A CrossEngage account.
* User data (including phone numbers).

### Loading user data into CrossEngage <a href="#loading-user-data-into-crossengage" id="loading-user-data-into-crossengage"></a>

**Configuring user attributes**

We suggest you use the “traits.phone” user attribute when using LinkMobility. You do, however, have the option to choose which attribute stores your users' phone numbers when setting up the integration. The phone number of the user should be in the international format. (example: +49 1234 56789 or +49123456789)


# Set up Link Mobility Integration

**Necessary credentials**

To set up this integration, you’ll require a System ID and Password for LinkMobility SMPP – please contact your LinkMobility account manager for SMPP credentials.

### **Configure LinkMobility integration in CrossEngage**

* In the CrossEngage app, navigate to Settings > Integrations
* Click the “Add new integration” button in the top right corner of the page.

<figure><img src="/files/zfWLFaM1kVBGbSAJoguR" alt=""><figcaption></figcaption></figure>

* Search for Link Mobility and click Set Up.

<figure><img src="/files/dbAruWRKsYNZNEPdhEtO" alt=""><figcaption></figcaption></figure>

* Give the integration a descriptive name.
* Enter the SMPP System ID and Password provided to you by your LinkMobility account manager. This is **not** the same as your REST API Login/Password.

<figure><img src="/files/Da1td39KQ3VpgpbD5b92" alt=""><figcaption></figcaption></figure>

* Choose the attribute that stores your users' phone numbers.

<figure><img src="/files/ZCxsmuRrxJ7598a67Dnz" alt=""><figcaption></figcaption></figure>

* Click “Apply”.

{% hint style="info" %}
The **traits.phone** user attribute is a default string type attribute created by CrossEngage. If you haven’t created your own custom user attribute to store phone numbers, the default attribute “traits.phone” can be used.&#x20;
{% endhint %}


# Create a Campaign Message

* Log in to your CrossEngage account.
* Go to “Campaigns” and click “Create Campaign” in the top right corner of the page.

<figure><img src="/files/DvQlgHZCTkPXaSHxJwDz" alt=""><figcaption></figcaption></figure>

* Choose whether you want to create an Audience or a Realtime campaign. Information about the distinction between these types of campaigns found [here](/data-and-engagement-platform/campaign-management/campaigns).
* Once you have created your campaign and filled in the “Campaign setup” and “Target group” sections, go to the `Messages` section and click `Create new message`.
* Select `SMS` from the dropdown menu. The message setup screen will open.

<figure><img src="/files/GdzryIGtHuwHbCfJaI15" alt=""><figcaption></figcaption></figure>

#### Message setup <a href="#message-setup" id="message-setup"></a>

**Sender info**

* Enter the sender’s information in the sender field. This field accepts alphanumeric values and may contain handlebars. It can either be a telephone number in an international format, for example, “+49 1234 56789”, or an alphanumeric string such as “companyName”.

**Message text**

* Enter the SMS text you would like to send in the message text block. You can use handlebars to personalize the messages – learn more about handlebars [here](/data-and-engagement-platform/messages/personalization).

<figure><img src="/files/aIHwMah2MPpO0FdwJE56" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
LINKMobility charges extra for long messages. For example, a long message split into 3 parts will be charged at 3 times the rate of a single message.

You will have to pass the opt-out / in data via our API for opt-out management when using LINKMobility.
{% endhint %}


# SFTP


# Set up SFTP Integration

* In the CrossEngage app, navigate to Settings > Integrations.
* Click the Add new integration button in the top right corner of the page.

<figure><img src="/files/zfWLFaM1kVBGbSAJoguR" alt=""><figcaption></figcaption></figure>

* Search for "CrossEngage".
* Click Set up and select "Export" from the dropdown menu. The (S)FTP upload’ integration form will open.

<figure><img src="/files/UB9QICRCyRNm8jM9cNUS" alt=""><figcaption></figcaption></figure>

* Give your integration a clear, descriptive name
* Select the desired file transfer protocol. CrossEngage supports the following file transfer protocols: FTP, SFTP, FTPS
* Fill in your file transfer settings, including the Port, Host, Username, and Password
* Choose whether the Connection mode is ‘Active’ or ‘Passive.’
* Select whether you wish to set up Encryption, in which case you will have to set a password
* Set the file path to which the exported files should be exported
* Set the file properties of the exported CSV files
* Click Save

<figure><img src="/files/L8S4VZCrq5pgl6S4x7nX" alt=""><figcaption></figcaption></figure>


# Create a Campaign Message

* Log in to your CrossEngage account.
* Go to `Campaigns` and click `Create new campaign` in the top right corner of the page.

<figure><img src="/files/yEh1715nKo4tR0vFZuhQ" alt=""><figcaption></figcaption></figure>

* Choose whether you want to create an Audience or a Realtime Campaign. Information about the distinction between these types of campaign can be found [here](/data-and-engagement-platform/campaign-management/campaigns).
* Once you have created your campaign and filled in the "Campaign Setup" and "Target Group" sections, go to the `Messages` section and click on `Create new Message`.
* Select `SFTP Upload` from the dropdown menu. The message setup screen will open.

<figure><img src="/files/BTgB3rH8ieA0Tx6UiKfa" alt=""><figcaption></figcaption></figure>

* Under the “Send via integration” heading, select the CrossEngage integration that you set up earlier.

<figure><img src="/files/CNkM8kgvCqOl1slQJi7E" alt=""><figcaption></figcaption></figure>

### CSV File Properties

* Choose a field or multiple fields for the filename. It is important to set up meaningful names for your files, so that files can be identified correctly later. For example, if you are exporting files daily, you can use the "Date" field to generate a unique filename every day.
* Choose your compression scheme. You can compress your file with .zip or .gzip, or leave them uncompressed.

<figure><img src="/files/qBK7q8AjOkRXDdf6ne6H" alt=""><figcaption></figcaption></figure>

* Choose whether a header row with Column names should be added to the file.
* Choose your delimiter. Here we use a comma (,) as it is commonly used as a delimiter.
* Choose row delimiter. This is the character indicating the end of a row, usually entered with the "Enter" key.
* Choose a wrapper. This is the character used to enclose all values. Here we use double quotations (").
* Choose your escape character. When a computer reads this file, it needs to distinguish between the wrapper and the same character used inside a field. Here we are using double quotations (") again, as the CrossEngage feeds can read this escape sequence.

<figure><img src="/files/gGIDOaBZQe87f9rPK9aD" alt=""><figcaption></figcaption></figure>

* Lastly, create the table structure of your file. Here you need to define what fields will be added to the CSV file. You can export User traits directly, or combine them by writing [Handlebars](/data-and-engagement-platform/messages/personalization).

<figure><img src="/files/IYWV3pKODdezjjr0f55H" alt=""><figcaption></figcaption></figure>

* Click Save.


# Direct Mail


# Optilyz


# Set up Optilyz Integration

Before you begin, you will need the following:

* optilyz account
* CrossEngage account
* User addresses

## **Fetching an API Key**

An optilyz API key allows CrossEngage to connect to your optilyz account. To obtain it:

* [*Log in*](https://www.optilyz.com/dashboard/#/auth/signin) to your optilyz account.
* Click `Automations` in the left panel menu.
* Copy the API key located right under the title of the page.

<figure><img src="/files/EH5wcK49F0AXoKKNoCdH" alt=""><figcaption></figcaption></figure>

## Setting Up an optilyz Integration in CrossEngage

* In the CrossEngage app, navigate to `Settings` > `Integrations`.
* Click the `Add new integration` button in the top right corner of the page.

<figure><img src="/files/zfWLFaM1kVBGbSAJoguR" alt=""><figcaption></figcaption></figure>

* Search for optilyz, then click `Set up`.

<figure><img src="/files/eQgYPZRxzxX4NmHLSS0A" alt=""><figcaption></figcaption></figure>

* Give the integration a descriptive name.
* Paste the API key that you copied from your optilyz account during the previous steps into the "API key" field and click `Connect`.

<figure><img src="/files/WmRVcgIuO0XjiFU8wkW5" alt=""><figcaption></figcaption></figure>

### Value Mapping

Value mapping allows you to pass user information from CrossEngage to optilyz so you can perform better content personalisation.

* It is possible to set up a value mapping at this point if you wish to do so. There are three types of value mapping that you can set up:
  * User Attributes
  * [Handlebars](https://documentation.crossengage.io/personalisation/personalisation)
  * Static Values

<figure><img src="/files/PVJET8Mkk0KpWmEoZF9E" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/5ygH2virv1ExV0PFuNkS" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/aLdCQkcrDLv1CtLekFwz" alt=""><figcaption></figcaption></figure>

* Click `Apply` to save the Integration.


# Create a Campaign Message

## Using optilyz in a Campaign

* Log in to your CrossEngage account.
* Go to `Campaigns` and click `Create new campaign` in the top right corner.cam

<figure><img src="/files/DvQlgHZCTkPXaSHxJwDz" alt=""><figcaption></figcaption></figure>

* Choose whether you want to create an Audience or a Realtime campaign.
* Once you have created your campaign and filled in the “Campaign setup” and “Target group” sections, go to the `Messages` section and click `Create new message`.
* Select `Direct mail` from the dropdown menu. The message setup screen will open

<figure><img src="/files/tU0uXTANFg0wTr0vZ0pV" alt=""><figcaption></figcaption></figure>

* Under the “Send via integration” heading, select the optilyz integration that you set up earlier.

<figure><img src="/files/qujagsKYLu9muebKreXd" alt=""><figcaption></figcaption></figure>

## Automation

* To fill in the Automation field, you will need to have a created Automation in optyliz.
* If you have created automation(s) choose the one you want and skip the following section. If you do not have any yet, follow the steps in the section below.

<figure><img src="/files/piUEmWRiTNLMCJUxqhG4" alt=""><figcaption></figcaption></figure>

## Creating an Automated Mailing in optyliz

{% hint style="info" %}
CrossEngage only displays automations that are Live in your optilyz account.
{% endhint %}

* Log in to your optilyz account.&#x20;
* Go to `Automations` in the left panel menu.
* Click`New Automation` in the top right corner of the page.

<figure><img src="/files/UJlMRdl1GcgPFk1DLJK2" alt=""><figcaption></figcaption></figure>

* Give the automated mailing a descriptive name so that you can easily identify it later.
* Choose the delivery country.

<figure><img src="/files/IpgJNQ2eM14ccIaGZdgL" alt=""><figcaption></figcaption></figure>

### 1) Postage

* Mailings are created on a minimum volume basis. Select the minimum recipient count to send out a mailing.
* Set mailing dates. By default, mailings can be created on any business day.

<figure><img src="/files/8NJ3xeha5ltJYci5FUQD" alt=""><figcaption></figcaption></figure>

* Choose whether Optilyz should include or exclude unverified or duplicated addresses, suspicious names or missing names in mailings.

<figure><img src="/files/a8GnIoyVV3O82nQqUH5B" alt=""><figcaption></figcaption></figure>

### 2) Mail Materials

* Select the mail materials that you would like to use.
* After selecting all mail materials, click `Save and Configure`.

<figure><img src="/files/MGxUdqWsSDjCvZjCTy4s" alt=""><figcaption></figcaption></figure>

* Set the configuration of each mailing material by clicking `Review Configuration` and then choosing the right format, grammage, material, number of pages, color mode and personalisation.&#x20;
* When ready, click `Confirm`.

{% hint style="info" %}
You can learn more about the optimal configuration of your mail materials by hovering your cursor over the information icon beside each title within the configuration, or by reading [this article](http://help.optilyz.com/en/support/solutions/articles/43000493682-which-formats-does-optilyz-offer-).
{% endhint %}

### 3) Visuals

* Upload your final design of the mailing material. Leave the personalisation and address fields blank.
* Add a voucher code if you wish (see the next section).
* Upload a final design in a similar fashion to the first step, but this time fill in the address and personalised data to show optilyz how to print them. Learn more about personalising your designs [here](http://help.optilyz.com/en/support/solutions/articles/43000493959-how-do-i-personalize-my-designs-).

<figure><img src="/files/ZpxubP05qgxuOTLPHYLe" alt=""><figcaption></figcaption></figure>

### Voucher Codes

* Choose whether you want a
  * **Personalised Voucher** - each customer receives a unique voucher.
  * **Non-Personalised Voucher** - all recipients receive the same voucher.

#### Setting up a Personalised Voucher

* To add a Personalised Voucher, you need to have a voucher pool set up in your CrossEngage account. To set up a voucher pool go to `Settings` > `Vouchers`. [Learn here](/data-and-engagement-platform/messages/vouchers/creating-vouchers) how to set up the voucher pool.
* Once the voucher pool is set up:
  * Copy the name and paste it into the `Voucher pool name` line.&#x20;
  * Click `CONTINUE` and `SAVE`.

#### Non-Personalised Voucher

* Insert the Voucher Code.
* Click `SAVE`.

### 4) Summary

* Double check that everything is set up to your specifications.
* Click `ACTIVATE`.
* Select the created Automation in the CrossEngage campaign message.


# Webhooks


# Single Webhook


# Set up Webhook Integration

A webhook delivers data to other applications in real-time. Unlike typical APIs where frequent calls must be made to obtain real-time data, webhooks can be triggered automatically, for example in response to user events.

Before you begin, you should have the following information on hand:

* The destination URL, method and content type you would like to use
* If the destination URL requires authentification, please ensure you have the username and password that should be used when sending the webhook
* If you use a header for authentication or require other special headers, please also have these on hand

### Setting up a Webhook Integration

* In the CrossEngage app, navigate to `Settings` > `Integrations`.
* Click the `Add new integration` button in the top right corner of the page.

<figure><img src="/files/zfWLFaM1kVBGbSAJoguR" alt=""><figcaption></figcaption></figure>

* &#x20;Search for 'webhook'  and click **Set up.**

<figure><img src="/files/ZjBx8T9HDE9twkpBjekW" alt=""><figcaption></figcaption></figure>

Using this information, you can now complete the setup form.

## Sender Info

The sender information is the method (POST or PUT) and Destination URL that will be used to dispatch the webhook.

## Authentication

You are able to use three types of authentication when using Webhooks on CrossEngage:

* Basic Authentication
* WSSE Authentication
* OAuth 2 authentication.&#x20;

### Append HTTP headers

If you require any special headers or authentication headers, please add the key - value pairs here.

### Content type

At this stage, you are able to choose what type of content the webhook will send to your destination URL. We currently support Javascript, JSON, XML and URL-encoded content types.

### Default Message Content

Since the structure of a webhook will not considerably change over the time, you can prefill the default message at this stage.

The information entered here will appear by default in every new message created on CrossEngage.

### Additional Properties

You can define additional properties that will be added to events.

<figure><img src="/files/MsGZSWWGmmBERgUAOscz" alt=""><figcaption></figcaption></figure>


# Create a Campaign Message

You can create your first message by selecting the newly created Webhook integration from the "Send via integration dropdown". We strongly recommend giving your message a descriptive name, which helps you identify what the Webhook is doing at a glance.

## Delivery Settings

In this section, you can preview the Destination URL, Content type and Custom Headers as well as add **Dynamic URL parts.**

**Dynamic URL parts** are variable URL parameters that can serve as uniform resource identifiers or query parameters. In this field, you can type both static text and dynamic data by using our personalisation language HandleBars. To find out more about HandleBars, [click here](/data-and-engagement-platform/messages/personalization).

<figure><img src="/files/ltL46ra6WklsEqwSFDtq" alt=""><figcaption></figcaption></figure>

## Message Content

Once having reviewed and, optionally, defined any dynamic URL parts, you are ready to edit your message.

If you have defined a default message, you will find this in the Message Content area every time you create a new message.

According to the type of "Content" you have selected when setting up the integration, you can either enter "Plain text" or fill the "URL encoded form" with key - value pairs.

CrossEngage will validate your syntax to help you avoid small errors and will help you find the line where an error occurred.

<figure><img src="/files/fSOQuqDMEhqA0v2q4WHU" alt=""><figcaption></figcaption></figure>

## Previewing your message

To preview your message, click on the "Preview message" button on the bottom left part of your browser page.

The new CrossEngage preview functionality allows you to render any dynamic data entered through HandleBars and load multiple users which you can then browse through at your discretion.

Please be aware that "Previewing" is only available for Audience campaigns as Realtime Campaigns may be based on dynamic data obtained from trigger events.

<figure><img src="/files/iLUwO8Nh3OAH85DZWNl3" alt=""><figcaption></figcaption></figure>

## Sending to a test URL first

CrossEngage allows you to send a test webhook to staging environment first. For this, we have chosen "Hookbin". To start the testing process, please go to [Hookbin](https://hookbin.com/) first. You can then "Create a new endpoint", which will provide you with the URL that can be used for testing.&#x20;

You can then use the generated URL, to send a test via CrossEngage by pasting it on the above form and clicking the "Send test" button.&#x20;

Once having reviewed and tested the webhook, you can then save and activate the campaign.&#x20;


# Response Data and Custom Events

When using Webhooks, CrossEngage generates and stores 3 different types of events:

* Webhook Delivered - every time we receive a 2xx response from the destination URL
* Webhook Bounced - every time we receive a 5xx response from the destination URL
* Errors - every time we receive a 4xx response from the destination URL

You will be able to view these events in the statistics graph on every campaign.

## Custom events

If you would like to use your own custom events, you can send these to our "Events API endpoint", using the event structure below. To find our more about our public API, [click here](https://jsapi.apiary.io/apis/usermanagementv1/reference/event-management.html) and go to **Event Management**.

Before sending custom events, please ensure that you contact your dedicated Customer Success Manager or send an email to <support@crossengage.io> to ensure that the "Events" and "Event Properties" are activated for usage. In your request, please include the required types of properties (e.g. STRING, FLOAT) and their names, so that our team can quickly build these for you.

```javascript
{
	"campaignId": "Campaign ID on CrossEngage",
	"campaignExternalReferenceId": "Campaign ID on CrossEngage",
	"messageId": "Message ID on CrossEngage",
	"channelConfigExternalReferenceId": "Message ID on CrossEngage",
	"channelConfigId": 31,
	"event": "whatsapp.xxx",
	"properties": {
		xxx:xxx
	}
}
```


# Batch Webhook


# Set up Batch Webhook Integration

Single Webhooks are sent when an event for which response data has been requested is completed. As a result, data is sent at intervals. Therefore, these webhooks are ideal for realtime campaigns.

Batch Webhooks, on the other hand, are suitable if you expect a large amount of data to come at once.

Before you begin, you should have the following information available:

* The destination URL, method and content type
* The username and password to be used when sending the webhook (if the destination URL requires authentication)
* The authentication header (or other special headers if they are used for authentication)

## **Setting up a Batch Webhook Integration**

* In the CrossEngage app, navigate to `Settings` > `Integrations`.
* Click the `Add new integration` button in the top right corner of the page.

<figure><img src="/files/zfWLFaM1kVBGbSAJoguR" alt=""><figcaption></figcaption></figure>

* Search for 'Webhook' and click Set Up.

<figure><img src="/files/ZjBx8T9HDE9twkpBjekW" alt=""><figcaption></figcaption></figure>

Using this information, you can now complete the setup form.

## Sender Info

The sender information is the method (POST or PUT) and Destination URL that will be used to dispatch the webhook.

## Authentication

You are able to use three types of authentication when using Webhooks on CrossEngage:

* Basic Authentication
* Header Authentication
* URL based authentication.

Please note that OAuth authentication is not currently supported. For more information regarding supported authentication, please reach out to your dedicated Customer Success manager or send an email to <support@crossengage.io>.

### Content type

Choose the content type application/JSON.

### Message Batching

Turn on Message Batching, and choose a batch size from 50 to 1000.

### Append HTTP headers

If you require any special headers or authentication headers, please add the key - value pairs here.

### Default Message Content

Since the structure of a webhook will not considerably change over the time, you can prefill the default message at this stage.

The information entered here will appear by default in every new message created on CrossEngage.

### Additional Properties

You can define additional properties that will be added to events.


# Create a Campaign Message

* Log in to your CrossEngage account.
* Go to `Campaigns` and click `Create new campaign` in the top right corner of the page.

<figure><img src="/files/DvQlgHZCTkPXaSHxJwDz" alt=""><figcaption></figcaption></figure>

* Choose an Audience campaign.
* Once you have created your campaign and filled in the “Campaign setup” and “Target group” sections, go to the `Messages` section and click `Create new message`.
* Select `Webhook` from the dropdown menu. The message setup screen will open.

<figure><img src="/files/ZHwaA2pPM411xcop5D4f" alt=""><figcaption></figcaption></figure>

* Under the “Send via integration” heading, select the webhook that you set up earlier.
* If you are using different endpoints, you can add the specific URL part in the "Delivery Settings" section, instead of making a new integration for it.
* If you are using different endpoints you can add the specific URL part by checking the *?* the "Delivery Settings" section instead of making a new integration for it.
* Under "Message Content" you will find the JSON text you set up in the Integration step. You can add more text depending on your needs.

#### **1) Passing one variable**

* Put the following code in to the "Message Content" field:

`{"email": "{{batch:email}}"}`

* Adjust the code to include your desired user attribute by changing the name of the user attribute or handelbar. For example, you can write "firstName" instead of "email", which would appear as&#x20;

  `{"firstName": "{{batch:firstName}}"}`.
* Select the right variable in Value Mapping: you can select traits (user attributes) as well as handlebars.

<figure><img src="/files/1OcPL7TflyB3hAYNc2zS" alt=""><figcaption></figcaption></figure>

#### **2) Passing more than one variable**

* Copy and paste the following code into the Message Content field:

`{"users": "{{batch:users}}", "email": "{{batch:email}}"}`

* Adjust the code to include your desired user attribute by changing the name of the user attribute or handelbar. For example, you can write "firstName" instead of "email", which would appear as&#x20;

  `{"firstName": "{{batch:firstName}}"}`.
* Select the right variables in the Value Mapping section.

#### **3) Passing an array of objects**

* Copy and paste the following code into the "Message Content" field:

`{"userattribute": "{{batch:userattribute}}"}`

* Select the right variables and substitute the handlebar below as the value for the "userattribute" variable:

`{"email": "{{user.[traits.email]}}","country": "{{user.[traits.businessUnit]}}","address": "{{user.[traits.address]}}" }`

* This is how the webhook delivery should look like:

```
{"email": "abc@crossengage.io","country": "DE","address": "abcdefg"},
{"email": "bcd@crossengage.io","country": "UK","address": "bcdefgh"},
{"email": "cde@crossengage.io","country": "DE","address": "cdefghi"}
```

In similar fashion to a singular webhook, the users will receive "webhook.sent" event.

## **Good to Know**

* Make sure that the webhook URL is "https" not "http".
* Make sure the other endpoint gives fallback as well.
* If the endpoint has a restriction, such as not allowing an empty field, it might reject/fail a user. If one user is rejected, the whole batch will fail.
* You can use waithook/hookbin to test. Please note that waithook will not give you https support - for this you can use hookbin instead.
* Default content:

`{"users": "{{batch:userupdate}}"}`

* Start your campaign. If you are using it for testing you can monitor it in hookbin with the endpoint which you have just created. You will see:
  * Request details (time etc)
  * HTTP HEADERS
  * QUERY STRING
  * BODY
  * FILE UPLOADS
  * COOKIES


# Zenloop via CrossEngage Webhook


# Set up Zenloop Integration (via CrossEngage Webhook)

Before you begin, you will need the following:

* CrossEngage account
* zenloop Account

### **Fetch your Zenloop API Token**

To access access your API Token in Zenloop, go to Settings -> zenAPI.

<figure><img src="/files/0ikX0JgP91NIllQh1QbQ" alt=""><figcaption></figcaption></figure>

You can also fetch your token/key using an API Client Application such as Postman. Simply send a POST request with your username and password to the Zenloop API, and you will receive the key labeled as "jwt".

<figure><img src="/files/abkdN43SIz4VB0X2FvJr" alt=""><figcaption></figcaption></figure>

### Set up CrossEngage Webhook Integration

* In the CrossEngage app, navigate to `Settings` > `Integrations`.
* Click the `Add new integration` button in the top right corner of the page.

<figure><img src="/files/zfWLFaM1kVBGbSAJoguR" alt=""><figcaption></figcaption></figure>

* &#x20;Search for 'webhook'  and click **Set up.**

<figure><img src="/files/ZjBx8T9HDE9twkpBjekW" alt=""><figcaption></figcaption></figure>

Using this information, you can now complete the setup form.

* Method: POST
* Destination URL: <https://api.zenloop.com/v1/surveys>
* Authentication: No authentication
* Append HTTP Headers: Add a header with the header key "authorization" and the header value "Bearer YOUR-API-TOKEN".
* Content type: application/JSON
* Click Apply.

<figure><img src="/files/a4IEuJSIVD45WPlMSbsI" alt=""><figcaption></figcaption></figure>


# Set up Zenloop Survey

Zenloop is an integrated experience management platform which enables users to collect, cluster and analyze customer feedback they receive through various channels along their customer journey.

For more information, click [here](https://www.zenloop.com/en).

Follow these steps to set-up your zenloop Email survey.

* Go to the Collect Page in Zenloop, and choose Zenloop Email.
* Customise your survey styling using zenloop’s Survey Editor. For more information, [click here](https://support.zenloop.com/de/articles/5520444-customising-your-survey).

<figure><img src="/files/2RrUB3x0nDaBBVs6irVN" alt=""><figcaption></figcaption></figure>

* Once you’ve customised your survey, click Next to go to **Recipients.**
* In the Recipients tab, click on Zenloop API and copy the Public Hash ID. This will be needed later to set up the Integration in CrossEngage.

<figure><img src="/files/8Fmq1W1BC6SEX6RqlcKX" alt=""><figcaption></figcaption></figure>

* **Launch** your survey. Please note, survey dispatch will be delayed until recipients are sent to the survey via API


# Create a Campaign Message

* Log in to your CrossEngage account.
* Go to Campaigns and click "Create new campaign" in the top right corner of the page.

<figure><img src="/files/DvQlgHZCTkPXaSHxJwDz" alt=""><figcaption></figcaption></figure>

* Choose whether you want to create an Audience or a Realtime campaign. Information about the distinction between these types of campaigns found [here](/data-and-engagement-platform/campaign-management/campaigns).
* Once you have created your campaign and filled in the “Campaign setup” and “Target group” sections, go to the `Messages` section and click `Create new message`.
* Select `Webhooks` from the dropdown menu. The message setup screen will open.

<figure><img src="/files/ZHwaA2pPM411xcop5D4f" alt=""><figcaption></figcaption></figure>

* Under the “Send via integration” heading, select the Webhook that you set up earlier.
* In Delivery Settings, select "Add URL part," and add the following to the destination URL: **`/Public_Hash_ID/survey_recipients`** . Please make sure that "/survey\_recipients" is added after your public hash id.

<figure><img src="/files/6dgNkASm8TH6XOHPZR3x" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The Public Hash ID is the same ID you copied while [setting up your Zenloop Survey](/data-and-engagement-platform/messages/integrations/channels/webhooks/zenloop-via-crossengage-webhook/set-up-zenloop-survey). You can find the Public Hash ID for all Surveys in your Zenloop Account in Settings -> zenAPI.
{% endhint %}

* Fill in the Message box using JSON format. To better understand the possibilities of this integration, see the text below, which uses Handlebars as well.

### **Example JSON Message**

{% code overflow="wrap" lineNumbers="true" %}

```json
{
  "send_at": "{{computeDate '{"timePhrase": "+ 0 day", "outputFormat": "yyyy-MM-dd"}'}}T{{computeDate '{"timePhrase": "+ 0 day", "outputFormat": "HH:mm:ss"}'}}Z",
  "recipient": {
    "identity": "{{user.[traits.email]}}",
    "identity_type": "email",
    "first_name": "{{user.[trait.firstName]}}",
    "last_name": "{{user.[trait.lastName]}}",
    "properties": [
      {"name": "country", "value": "{{user.[trait.country]}}"},
      {"name": "gender", "value": "{{user.[trait.gender]}}"},
      {"name":"ce_externalId","value":"{{user.[traits.externalId]}}"}
    ],
    "metatags": {
      "survey_question": "How likely are you to recommend %[question subject]?",
      "question_subject": "metatags",
      "request_for_comment_all": "Tell us a bit more about why you chose %[score] for metatags",
      "thank_you_link_text_all": "example text",
      "thank_you_link_url_all": "www.example.com",
      "thank_you_note_all": "Thanks for your feedback!"
    }
  }
}
```

{% endcode %}

### Explanation of Example Text

```json
  "send_at": "{{computeDate '{"timePhrase": "+ 0 day", "outputFormat": "yyyy-MM-dd"}'}}T{{computeDate '{"timePhrase": "+ 0 day", "outputFormat": "HH:mm:ss"}'}}Z",
```

This section of the example JSON text defines the time at which the message will be sent. This formulation will print year-month-date, and hour-minute-second. The ‘T’ and ‘Z’ in this formula is a requirement of zenloop’s ‘send\_at’ format. Note that this section is not necessary: if not provided, the message will be sent anyway.

```
"recipient": {
    "identity": "{{user.[traits.email]}}",
    "identity_type": "email",
    "first_name": "{{user.[trait.firstName]}}",
    "last_name": "{{user.[trait.lastName]}}",
    "properties": [
      {"name": "country", "value": "{{user.[trait.country]}}"},
      {"name": "gender", "value": "{{user.[trait.gender]}}"},
      {"name":"ce_externalId","value":"{{user.[traits.externalId]}}"}
    ],
```

This section of the example JSON text defines the recipient of the message. The Handlebars in this message allow the recipient field to be personalized, inserting specific users’ email addresses, first names, last names, countries, and genders. For more information on Personalisation in CrossEngage, check our documentation [here](/data-and-engagement-platform/messages/personalization).

```
"metatags": {
      "survey_question": "How likely are you to recommend %[question subject]?",
      "question_subject": "metatags",
      "request_for_comment_all": "Tell us a bit more about why you chose %[score] for metatags",
      "thank_you_link_text_all": "example text",
      "thank_you_link_url_all": "www.example.com",
      "thank_you_note_all": "Thanks for your feedback!"
    }
```

This section of the example JSON text defines metatags, which are used for personalizations in Zenloop. The question in the above example would show, “How likely are you to recommend metatags?” For further information, check the Zenloop integration [here](https://docs.zenloop.com/docs/metatags-implementation)

{% hint style="danger" %}
If the handlebars you have included in the message can't be resolved, webhook dispatch will fail.
{% endhint %}


# Set up Zenloop Survey via ESP

## **Set Up your zenloop Survey**

* Go to the Collect Page in Zenloop, and choose Email Embed.
* Follow [these steps](https://support.zenloop.com/de/articles/846117-setting-up-email-embedded-channel) to set-up your zenloop Email survey.
* Customise your survey styling using zenloop’s Survey Editor. For more information, [click here](https://support.zenloop.com/de/articles/5520444-customising-your-survey).
* Click next to go the the **Implement** Step.
* Set the Email Marketing Platform as Custom.
* copy the HTML code snippet to use in CrossEngage.

<figure><img src="/files/BjMYbSSIiSSpHALtz11t" alt=""><figcaption></figcaption></figure>

* Setup a campaign in CrossEngage using an email integration and add the HTML code you copied in Step 4.

<figure><img src="/files/idL5hdqQfOKKwtaP0AHh" alt=""><figcaption></figcaption></figure>

* In order to attach Recipient Identities & [Properties](https://support.zenloop.com/de/articles/825164-choosing-your-properties), you must alter each URL in the code (there can be up-to 11, depending on the scale being used) using handlebars. The links must be changed as follows. For more information, see the Zenloop documentation [here](https://support.zenloop.com/de/articles/844530-adding-recipient-identities-and-properties-to-email-embedded-survey).

```
https://responses.zenloop.com/web/response/[Survey-Hash-ID]/email_embed/10?is_a_test=false&identity={{user.[traits.externalId]}}&identity_type=custom&first_name={{user.[traits.firstName]}}&last_name={{user.[traits.lastName]}}&properties[ce_externalId]={{user.[traits.externalId]}}
```

{% hint style="info" %}
You can see the Hash ID for your Zenloop Surveys in Settings -> zenAPI.
{% endhint %}

* Activate and run your Campaign.


# Obtain Response Data

### **What you should be aware of**

* The survey needs to run through CrossEngage to Zenloop for us to be able to map the response data to respective users on our side, see the documentation on [how to create a CrossEngage campaign message with Zenloop](/data-and-engagement-platform/messages/integrations/channels/webhooks/zenloop-via-crossengage-webhook/create-a-campaign-message).
* This solution we have provided here will only work, if the externalId (also used in CE) is provided to Zenloop as dedicated property within Zenloop.
* The users/events can be ingested hourly or daily.
  * Hourly (every hour we fetch Zenloops Response Data for the previous hour)
  * daily (every day we fetch yesterday's response data from Zenloop)
* At the moment this is restricted to 50 surveys.

### **Preparing the Setup on your side**

For this setup we will need the following information:

* Zenloop API Key
* CE Master API Key
* (Optional) List of campaign ids to be queried

Once you have the required API keys, please contact our Customer Operations team to set up Zenloop responses in CrossEngage. You can do so by filing a ticket on our [Customer Support Portal](/data-and-engagement-platform/help-and-support/reach-out-to-customer-support).

Once you have provided the required information to us, you will be able to see the following on the users who have responded to the survey:

* Traits:
  * `traits.lastNPSScore` represents the latest submitted NPS-Score
  * `traits.lastNPSDate` represents your customer's last submitted score

{% hint style="info" %}
These traits will be visible in User Profile > Attributes.
{% endhint %}

* Event: `Survey Completed`&#x20;
  * properties:
    * `properties.surveyId` represents Zenloop’s survey id
    * `properties.surveyName` represents Zenloop’s survey name
    * `properties.npsScore`
    * `properties.npsComment`
    * `timestamp` represents the time when your customer submitted the NPS (UTC time)&#x20;

{% hint style="info" %}
The event will be visible in e.g. **User Profile** > **Event History**.
{% endhint %}

```json
{
  "eventCategory": "CUSTOM",
  "eventClassId": 123456,
  "eventClassName": "Survey Completed",
  "eventTime": "2020-06-09T08:00:41+0000",
  "eventData": {
    "event": "Survey Completed",
    "properties.npsComment": "I can't recommend this enough to everyone",
    "properties.npsScore": "10",
    "properties.surveyId": "randomUUID",
    "properties.surveyName": "CrossEngage Response",
    "timestamp": "2020-06-09T08:00:41.000+0000"
  }
}
```


# Google Analytics via Webhook

### Find your Google Measurement ID and API Secret

To configure Google Analytics 4 via Webhook, you will need your Google Measurement ID and API Secret. Note that the Measurement ID and the API Secret should be selected from the relevant data stream.

* Log in to [Google Analytics](https://analytics.google.com/).
* Click on Admin.
* Under 'Property', go to Data Streams.

<figure><img src="/files/3UL90mKmJEiMN4fdgfZD" alt=""><figcaption></figcaption></figure>

* Click on the Data Stream you wish to connect to CrossEngage.

<figure><img src="/files/ogtVdtTYmrfUHazHr7Mc" alt=""><figcaption></figcaption></figure>

* Copy your measurement ID. This will be needed in CrossEngage.

<figure><img src="/files/qnp98Z1tMYayorrry73O" alt=""><figcaption></figcaption></figure>

* Scroll down to events. Click on 'Measurement Protocol API Secrets".
* If you have not yet created an API Secret, create a new Secret.
* Copy your API Secret. This will be needed in CrossEngage.

<figure><img src="/files/5I3pca6YnZRVZkTEBgfu" alt=""><figcaption></figcaption></figure>

### Configure Google Analytics via Webhook

* In the CrossEngage app, navigate to `Settings` > `Integrations`.
* Click the `Add new integration` button in the top right corner of the page.

<figure><img src="/files/zfWLFaM1kVBGbSAJoguR" alt=""><figcaption></figcaption></figure>

* Search for 'webhook'  and click **Set up.**

<figure><img src="/files/ZjBx8T9HDE9twkpBjekW" alt=""><figcaption></figcaption></figure>

Using this information, you can now complete the setup form.

* Method: POST
* Destination URL: [https://www.google-analytics.com/mp/collect?measurement\_id=\<yourMeasurementId>\&api\_secret=\<yourAPISecret>](https://www.google-analytics.com/mp/collect?measurement_id=yourMeasurementId\&api_secret=yourAPISecret)
* Authentication: No authentication
* Content type: application/JSON

<figure><img src="/files/W78v7Re4aJJLtL2283hb" alt=""><figcaption></figcaption></figure>

In the JSON text, paste the following JSON body:

```
{
    "client_id": "handlebar to fetch client id",
    "user_id": "handlebar to fetch user id",
    "events": [
        {
            "name": "event name",
            "params": {
                "param1": "xyz",
                "param2": "xyz"
            }
        }

]

}
```

<figure><img src="/files/z0RraItTzMTUvtNITkLB" alt=""><figcaption></figcaption></figure>

* Click 'Apply'.

You can now use this integration in a campaign. When using the integration in a campaign, update the campaign message with the handlebars, event name, and parameters.&#x20;


# Segment Transfer


# Facebook


# Set up Facebook Developer Account

Before you begin, you will need the following:

* CrossEngage account
* A Facebook App Administrator Account with Ads Management Standard Access

{% hint style="info" %}
For an explanation of Custom Audiences in Facebook for Developers, check their documentation [here](https://www.facebook.com/business/help/744354708981227) or [here](https://adespresso.com/blog/facebook-ads-custom-audiences-guide/).
{% endhint %}

### **Creating a Facebook Developer App**

* Log in to your Facebook Developer account [here](https://developers.facebook.com/).
* Go to "My Apps" in the main dashboard.
* Click on the Create App button. If this is your first time using Facebook for Developers, click ‘Getting Started,’ set up your account, and click “Create First App”.

<figure><img src="/files/kYCejklvf69dN3PtqbFu" alt=""><figcaption></figcaption></figure>

* Set “Business” as the application type. Click “Next”.

<figure><img src="/files/TLLPwp1PWZE9AOgfENFX" alt=""><figcaption></figcaption></figure>

* Name your new app and enter the contact email through which you will receive notifications.
* Click “Create App”.

<figure><img src="/files/BhGBNfwgrA8EznjwKp1L" alt=""><figcaption></figcaption></figure>

### **App Review**&#x20;

You will need to submit to [App Review](https://developers.facebook.com/docs/facebook-login/review/how-to-submit) before you continue. This may take several days.&#x20;

### **Checking Administrator Access**

If you have problems with the previous steps, be sure to check whether you have administrator access by completing the following steps:

* Log in to [https://business.facebook.com](https://business.facebook.com/).
* Click on the Business Settings button at the bottom left of your screen.
* Select “Users” > “People” from the navigation bar on the left.

<figure><img src="/files/nelf66uCQ5YBROH2n8ub" alt=""><figcaption></figcaption></figure>

* Find the desired app in the “Assigned assets” section and click on the arrow icon to the right.
* Make sure the “Manage app” permission under the “Admin access” title is activated.


# Optimizely


# Set up Optimizely Account

Before you begin, you will need the following:

* Optimizely Account&#x20;
* CrossEngage Account
* A website that implements the Optimizely snippet. See [this page ](https://support.optimizely.com/hc/en-us/articles/4410289783309-Custom-snippets-in-Optimizely-Web-Experimentation)for more information.
* User data that includes the Optimizely identifier

### Setting Up Dynamic Customer Profiles

Dynamic Customer Profiles (DCP) function as a storage facility for customer data on Optimizely. The data stored there can be used on platforms implementing the Optimizely snippet.

The process for setting up DCPs is explained in the [Personalization: Create Audiences with Dynamic Customer Profiles](https://help.optimizely.com/Target_Your_Visitors/Personalization%3A_Create_Audiences_with_Dynamic_Customer_Profiles) guide on Optimizely. Complete the following steps in the guide:

* Create a DCP Service
* Add a datasource
* Define attributes

### Creating an API Token

* In Optimizely, click on your profile in the bottom right corner.
* Go to the API Access Tab.
* Click on Generate new Token.
* Give your token a meaningful name, and click on Create.

<figure><img src="/files/eOV3wahT1L1cprwrMsyk" alt=""><figcaption></figcaption></figure>

An API token is required in order for CrossEngage to access the Optimizely API. Complete the steps in the [Generate an API token in Optimizely Classic](https://help.optimizely.com/Integrate_Other_Platforms/Generate_an_API_token_in_Optimizely_Classic) guide to generate an API token. Save this value, as it will be required for the CrossEngage integration setup later.

### Transferring User Data to CrossEngage

### Configuring User Attributes

During the DCP setup, you configured a unique ID in step 5 of [Add a datasource](https://help.optimizely.com/Target_Your_Visitors/Personalization%3A_Create_Audiences_with_Dynamic_Customer_Profiles#2._Add_a_datasource). In order to store this unique ID value in CrossEngage, you can either create a new trait or use an existing trait. The value used will be configured in the integration setup. Ensure that you include this trait when creating users in the next step.

### Creating users

Users can be loaded on to the CrossEngage platform via the API or through the User Feed. Consult the [Data Management](/data-and-engagement-platform/data-management) documentation to learn more.


# Google Analytics


# Set up Google Analytics Integration

Before you begin, you should ensure that you have access to a Google account with sufficient permission to access:

* Google Analytics Properties & Apps
* Google Analytics Custom Dimensions

If you do not have this level of access, you will not be able to proceed with setting up the integration. Please contact your Google Analytics account administrator to get access.&#x20;

### Set up Google Analytics Integration

* In the CrossEngage app, navigate to `Settings` > `Integrations`.
* Click the `Add new integration` button in the top right corner of the page.

<figure><img src="/files/zfWLFaM1kVBGbSAJoguR" alt=""><figcaption></figcaption></figure>

* Search for Google Analytics, click on the 'Set up' button.

<figure><img src="/files/iGXVJHCaqheDwkDfZbGJ" alt=""><figcaption></figcaption></figure>

* Give your integration a meaningful name.
* Click on "Sign in with Google".

<figure><img src="/files/JtZsXeUSvWqutwvLcCGy" alt=""><figcaption></figcaption></figure>

* After clicking the **Sign in with Google** button, a pop up or browser tab will open asking you to choose what account you would like to use in order to set up this Integration.

<figure><img src="/files/iw9hYgrk6BwbbdsWuPOH" alt=""><figcaption></figcaption></figure>

Click on the account which has sufficient access and follow the instructions, allowing CrossEngage access to **View & Manage Google Analytics data**.

<figure><img src="/files/FKAHdb4CyQe7JfgYciXU" alt=""><figcaption></figcaption></figure>

Once you allow access, you will be brought back to the **Integration Setup** form where you may now select the **Property or App** that you would like to use CrossEngage to transfer data to and the **User identifier** which should be included in the cookies created by Google Analytics.

The **User identifier** should represent the User ID which is intended to be a known identifier for a given user e.g. the ID you assign to a user upon account creation; It must not be PII (personally identifiable information). Read more about the different identifiers Google provides [here](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#user).

CrossEngage uses the **User identifier** user trait you select to send data to Google Analytics and match users. Selecting an incorrect **User identifier** user trait will corrupt data sent to Google Analytics by preventing products such as Google Adwords from displaying ads to users as the product will be unable to find users with the identifier selected. Please check with your technical team if you have any doubt about the **User identifier** your company uses to identify particular users.

<figure><img src="/files/d5AKRpwCqyTC3vIoYvku" alt=""><figcaption></figcaption></figure>


# Create a Campaign with Google Analytics

* Log in to your CrossEngage account.
* Go to "Campaigns" and click on "Create new campaign" in the top right corner.

<figure><img src="/files/DvQlgHZCTkPXaSHxJwDz" alt=""><figcaption></figcaption></figure>

* Choose whether you want to create an Audience or a Realtime campaign. Information about the distinction between these types of campaigns found [here](/data-and-engagement-platform/campaign-management/campaigns).
* Fill in the "Campaign setup" and “Target group” sections.
* Go to the "Messages" section and click the "Create new message" button.
* Select 'Segment Transfer' from the dropdown menu.

<figure><img src="/files/OBtSut6neuTdJH1a7zib" alt=""><figcaption></figcaption></figure>

* Under the 'Send via integration' heading, select the Google Analytics integration that you set up earlier.

### Google Analytics campaign

You can now define the Google Analytics Event that you would like to send to the selected CrossEngage segment (or qualifying Realtime campaign user). Google Analytics Events are defined with the following:

1. **Event Action** - This is defined by CrossEngage as **CrossEngage Event** to allow you to immediately differentiate CrossEngage transfers from other types of tracking events.
2. **Event Category** - Category allows you to usually define what type of interaction this event describes (e.g. Funnel Step 1)
3. **Event Label** - Label allows you to categorise events  (e.g. Reactivation Cycle)

<figure><img src="/files/BVO8mBxZhLw1ga1BzQBU" alt=""><figcaption></figcaption></figure>

* Optionally, you can also populate **Custom Dimensions** for users stored in your Google Analytics account with every event dispatch.

<figure><img src="/files/11asFRvfxgytRVBqXlgH" alt=""><figcaption></figcaption></figure>

**Custom Dimensions** allow you to transfer user data from CrossEngage to Google Analytics and use this within Google Analytics segmentation and build audience that can have any **Destination** (e.g. AdWords, Google Distribution Network) that you have set up & have access to. PII (Personal Identifiable Information) data should not be transferred to Google Analytics via CrossEngage due to GDPR restrictions.

### Understanding Response Data

At this time, when using Google Analytics, CrossEngage currently creates & stores only one type of event:

* Sent, generated when an event was sent to a Google Analytics user (in segmentation google.analytics.segment.transfer.sent).


# Using the Google Analytics Integration

The best use case for the Google Analytics Integration is to build dynamic segments in CrossEngage and transfer events to these users in Google Analytics. Once you have successfully transferred your users, you can use Google Analytics segmentation to build audiences which you can target through:

* Third-party sites ads through[ Google Display Network](https://support.google.com/adwords/answer/2404190?hl=en)​
* ​[Google Search Ads](https://support.google.com/adwords/answer/2471185?hl=en)​
* ​[Google Gmail Ads](https://support.google.com/adwords/answer/7019460?hl=en)​
* ​[Google Youtube Ads](https://support.google.com/adwords/answer/6340491?hl=en)​
* ​[Google Shopping Ads](https://support.google.com/adwords/answer/2454022?hl=en)​
* Any other service provided by Google that can be used as a destination in Google Analytics.

To build audiences in Google Analytics, follow the instructions below:

1. Navigate to **Settings** by clicking the gear on the lower left hand side of your screen.
2. Ensure you have selected the right property from the **Property** dropdown
3. Under the **Property** dropdown, click on **Audience Definitions**
4. Under Audience Definitions, click on **Audiences**

From this page, you can create segments and add CrossEngage transfer related conditions:

<figure><img src="/files/oHosIFgiVhjHQmaILjRH" alt=""><figcaption></figcaption></figure>

* Click on **New Audience** (or edit an existing one).
* Under the **Audience Definition** section click on **Create New.**
* Click on **Conditions**, located on the bottom left hand side of the screen.
* You can now add a CrossEngage event-related condition by clicking on the default existing condition type (first block), selecting **Event Action** (or Category/Label) and entering **CrossEngage** Event (or your defined Category/Label).
* Add any other conditions you would like to use.
* Save your **Audience** by clicking **Apply.**

<figure><img src="/files/NzLiGFaPwFlQkjEKBcbJ" alt=""><figcaption></figcaption></figure>

Having defined your **Audience** as ‘users that have received a CrossEngage event,’ you are now ready to select the audience’s destination:

1. First, enter an **Audience Name** for tracking purposes.
2. Click on **Next Step.**
3. Select the **Destinations** in which you would like to use your segment (e.g. Google Adwords, Display Network, etc.).
4. Click on **Publish** to save your newly created audience.

If you need additional help, please reach out to your Customer Success manager or [create a support ticket](/data-and-engagement-platform/help-and-support/reach-out-to-customer-support).

<figure><img src="/files/CPKkUNWjEBiFXYtDnd3A" alt=""><figcaption></figcaption></figure>


# Airship


# Set up an Airship Account

Before you begin, you will need:

* A paid Airship account.
* A CrossEngage account.
* User data (with named user ids)

### Generating a bearer token for an Airship project <a href="#generating-a-bearer-token-for-an-airship-project" id="generating-a-bearer-token-for-an-airship-project"></a>

Bearer tokens are used to authenticate grant and control permissions for entities using the Airship API, sending custom events into the system, or supporting a Real-Time Data Streaming integration. To generate a bearer token,

* Log in to your Airship account.
* Go to the ‘Settings’ page.

<figure><img src="/files/Fw3JG9gS64h5JmXoBi3v" alt=""><figcaption></figcaption></figure>

* Go to the ‘Tokens’ page.

<figure><img src="/files/2H4pAHlrUAtKipaBXqFI" alt=""><figcaption></figcaption></figure>

* Click on ‘Create Token'.

<figure><img src="/files/ZRWI373nn61DMwY88PU6" alt=""><figcaption></figcaption></figure>

* Give your token a name and choose the role ‘All Access’.

<figure><img src="/files/cyRVRcZHBcfQ5RMWhpgy" alt=""><figcaption></figcaption></figure>

Once the token is generated, store it safely as it is needed when you setup your Airship integration in CrossEngage.

### User identification in Airship <a href="#user-identification-in-airship" id="user-identification-in-airship"></a>

In Airship, users can be identified either by a Channel ID, which identifies each individual device, or by a Named User ID, which identifies individual users. The essential distinction between these two types of identification is that one client may own multiple devices. We currently support user identification with the named user id.

Airship allows you to configure a unique user identifier called the named user id. Messages sent to a Named User ID are automatically routed to all linked Device IDs.

Be sure to remember which option you’ve chosen, which will be necessary when you set up the integration in CrossEngage.

### Loading user data into CrossEngage <a href="#loading-user-data-into-crossengage" id="loading-user-data-into-crossengage"></a>

**Creating users**

You can either upload users via API call or via user feed.&#x20;

* Instructions on how to load users into the CrossEngage platform via API can be found in User Profile Management> Bulk User Management in our [API documentation](https://docs.crossengage.io/user-management/v2).&#x20;
* Instructions on how to load users into the CrossEngage platform via user feed can be found [here](/data-and-engagement-platform/data-management).&#x20;


# Set up an Airship Integration

**Necessary credentials**

To connect Airship projects to CrossEngage you need to provide the following credentials.

* Bearer token (The token you generated with ‘All Access’ role)
* App key
* Master secret

This information can be found in your Airship account. The App key and Master secret are available in the ‘Settings’ page.

<figure><img src="/files/K9UYkaIM0EDbQHUfRVx8" alt=""><figcaption></figcaption></figure>

**Configuring an Airship integration in CrossEngage**

* In the CrossEngage app, navigate to Settings > Integrations.
* Click the “Add new integration” button in the top right corner of the page.

<figure><img src="/files/zfWLFaM1kVBGbSAJoguR" alt=""><figcaption></figcaption></figure>

* Search for Airship under the Push Notification channel or Segment Transfer channel. Click on Set up and choose ‘Segment Transfer’.

<figure><img src="/files/BbqztOgxO4iou1ChWkp0" alt=""><figcaption></figcaption></figure>

* **The Airship form**

  Give the integration a descriptive name and enter the credentials collected from the Airship account.

{% hint style="info" %}
The name of the integration cannot be modified after the integration is configured.
{% endhint %}

<figure><img src="/files/nngxlXEXZkaA59SVYqjn" alt=""><figcaption></figcaption></figure>

You can use multiple projects in one form. Enter the Airship project name you want to connect to, the bearer token, the app key and the master secret.

Select the CrossEngage attribute that maps to the named user id on Airship side and click ‘Apply’.




---

[Next Page](/llms-full.txt/1)

