# Attentive Tag Cloud Mode Integration

After you have successfully [set up Attentive Tag as a destination]({{< ref "destinations/streaming-destinations/attentive-tag/setup-guide.md" >}}) in RudderStack, follow this guide to correctly send your events to Attentive Tag in [cloud mode]({{< ref "destinations/rudderstack-connection-modes.md#cloud-mode" >}}).

Find the open source transformer code for this destination in the [GitHub repository](https://github.com/rudderlabs/rudder-transformer/tree/main/src/v0/destinations/attentive_tag).
  
## Identify

You can subscribe or unsubscribe a user from an Attentive list using the [`identify`]({{< ref "event-spec/standard-events/identify.md" >}}) call.

{{< info >}}
The default behavior of `identify` call is to subscribe a user. To unsubscribe, you can pass `identifyOperation` as `unsubscribe` in the `integrations` object.
{{< /info >}}

### Subscribe users

RudderStack maps the following traits to the Attentive properties while subscribing a user:

| RudderStack trait | Attentive property | 
|:--------------------------------|:--------------------------|
| `traits.email`/`context.traits.email`/`properties.email` <br/> <span style="color: #4D4DFF;font-size:12px;">Required, if `phone` is not provided. </span> | `user.email` | 
| `traits.phone`/`context.traits.phone`/`properties.phone` <br/> <span style="color: #4D4DFF;font-size:12px;">Required, if `email` is not provided. </span> | `user.phone` |
| `integrations.attentive_tag.signUpsourceId` <br/> <span style="color: #4D4DFF;font-size:12px;">Required, if not specified in the RudderStack dashboard. </span>| `signUpSourceId` |
| `externalId` | `externalIdentifiers` | 
| `context.traits.customIdentifiers`/`traits.customIdentifiers` | `externalIdentifiers.customIdentifiers` | 

{{< info >}}
Note that:

- The `externalIdentifiers` property can be an array of objects containing identifiers like `clientUserId`, `shopifyId`, `klaviyoId`.
- RudderStack prioritizes the `signUpSourceId` property in the `integrations` object over the value specified in the **Sign Up Source ID** dashboard setting.
{{< /info >}}

A sample `identify` call to subscribe a user is as follows:

```javascript
rudderanalytics.identify("jbu3471", {
  "email": "alex@example.com",
  "phone": "+1-202-555-0146",
  "customIdentifiers": [{
    "name": "string",
    "value": "string"
  }]
}, {
  "externalId": [{
      "type": "clientUserId",
      "id": "144"
    },
    {
      "type": "shopifyId",
      "id": "224"
    },
    {
      "type": "klaviyoId",
      "id": "132"
    }
  ],
  "integrations": {
    "signUpSourceId": "347393"
  }
});
```
{{< warning >}}
The  `externalId` fields are case-sensitive. Also, RudderStack expects them to be in the above format for mapping them correctly.
{{< /warning >}}

### Unsubscribe users

You can set `identifyOperation` to `unsubscribe` in the `integrations` object to unsubscribe a user:

```javascript
rudderanalytics.identify("jbu3471", {
  "email": "alex@example.com",
  "phone": "+1-202-555-0146",
}, {
  "integrations": {
    "attentive_tag": {
      "identifyOperation": "unsubscribe",
    },
    "subscriptions": [{
      "type": "MARKETING",
      "channel": "TEXT"
    }],
    "notification": {
      "language": "en-US"
    }
  }
});
```

RudderStack maps the following traits to the Attentive properties while unsubscribing a user:

| RudderStack trait | Attentive property | 
|:--------------------------------|:--------------------------|
| `traits.email`/`context.traits.email`/`properties.email` <br/> <span style="color: #4D4DFF;font-size:12px;">Required, if `phone` is not provided. </span> | `email` |
| `traits.phone`/`context.traits.phone`/`properties.phone` <br/> <span style="color: #4D4DFF;font-size:12px;">Required, if `email` is not provided. </span> | `phone` | 
| `integrations.attentive_tag.subscriptions` | `subscriptions` | 
| `integrations.attentive_tag.notification` | `notification` |

{{< warning >}}
Passing an `email` attribute does not locate or unsubscribe a user from SMS subscription. Similarly, passing the `phone` attribute does not locate or unsubscribe a user from email subscription.
{{< /warning >}}

You can also unsubscribe a user from a channel by specifying it in `subscriptions` within the `integrations` object. The supported values for `subscriptions` are:

```javascript
"subscriptions": [{
    "type": "MARKETING" || "TRANSACTIONAL" || "CHECKOUT_ABANDONED"
    "channel": "TEXT" || "EMAIL"
  }]
```

{{< info >}}
You can also provide the `language` in the `notification` inside the `integrations` object to change the notification language. Currently, RudderStack supports only `en-US` and `fr-CA` as the notification languages, which are case-sensitive.
{{< /info >}}

### Use new Identify flow

{{< info >}}
This feature is currently in beta.
{{< /info >}}

The new Identify flow leverages the following Attentive APIs:

- [Identity API](https://docs.attentivemobile.com/openapi/reference/tag/Identity/): To associate a client user identifier or custom identifier(s) with other identifiers.
- [Custom Attributes API](https://docs.attentivemobile.com/openapi/reference/tag/Custom-Attributes/#tag/Custom-Attributes): For updating the user attributes or properties.

To use the new Identify flow, turn on the [**Enable new Identify flow** setting]({{< ref "destinations/streaming-destinations/attentive-tag/setup-guide.md#advanced-settings" >}}) during the destination setup.

{{< warning >}}
Your API key must have the necessary permissions to use the new Identify flow. Contact your Attentive representative for steps on enabling these permissions.
{{< /warning >}}

Note that:

- If you toggle off this setting, RudderStack uses the default [subscription]({{< ref "destinations/streaming-destinations/attentive-tag/cloud-mode.md#subscribing-users" >}}) / [unsubscription]({{< ref "destinations/streaming-destinations/attentive-tag/cloud-mode.md#unsubscribing-users" >}}) flows instead.
- In this flow, RudderStack **does not make** any user subscription or unsubscription API calls — to do so, you will need to use the `subscription_event` `track` call.

#### Identity API mappings

| RudderStack trait | Attentive property | 
|:--------------------------------|:--------------------------|
| `traits.email`/`context.traits.email`/`properties.email` | `email` | 
| `traits.phone`/`context.traits.phone`/`properties.phone` | `phone` |
| `context.externalId.[].shopifyId` | `shopifyId` | 
| `context.externalId.[].klaviyoId` | `klaviyoId` | 
| `context.externalId.[].clientUserId` | `clientUserId` | 
| `context.traits.customIdentifiers` / `traits.customIdentifiers` | `customIdentifiers` | 

#### Custom Attributes API mappings

{{< info >}}
RudderStack uses this API to send any traits in the `identify` call within the `properties` object of the request.
{{< /info >}}

| RudderStack trait | Attentive property |
|:----------|:--------------------------| 
| `traits.email`/`context.traits.email`/`properties.email` | `user.email` | 
| `traits.phone` / `context.traits.phone` / `properties.phone` | `user.phone` |
| `context.externalId` | `user.externalIdentifiers` | 

## Track

The [`track`]({{< ref "event-spec/standard-events/track.md" >}}) call lets you capture the user actions along with the associated properties.

{{< warning >}}
RudderStack does not trigger an event if the timestamp is older than 12 hours.
{{< /warning >}}

### Property mapping

RudderStack maps the following `track` call properties to the Attentive properties:

| RudderStack property | Attentive property | 
|:--------------------------------|:--------------------------|
| `event` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | `type` |
| `traits.email`/`context.traits.email`/`properties.email`  | `user.email` |
| `traits.phone`/`context.traits.phone`/`properties.phone` | `user.phone` | 
| `externalId` | `user.externalIdentifiers` | 
| `properties` | `properties` | 
| `originalTimestamp`/`timestamp` | `occuredAt` | 
| `properties.eventId` | `externalEventId` | 
| `context.traits.customIdentifiers`/`traits.customIdentifiers` | `user.externalIdentifiers.customIdentifiers` | 

{{< warning >}}
Note that:

- You must specify the timestamp in the ISO 8601 format.
- The event type is case-sensitive. For example, Attentive considers `Order shipped` and `Order Shipped` as different events.
- The keys of the `properties` object should not contain characters, like [`'`, `"`, `{`, `}`, `[`, `]`, \ , `,`]
{{< /warning >}}

### Subscription events

You can perform user subscription and unsubscription operations using the `subscription_event` `track` call.

A sample `subscription_event` is shown below:

```javascript
rudderanalytics.track("subscription_event", {
  "context": {
    "traits": {
      "email": "alex@example.com",
      "phone": "+1-202-555-0146"
    }
  },
  "channelConsents": [{
      "channel": "email",
      "consented": true
    },
    {
      "channel": "sms",
      "consented": false,
      // "type": "MARKETING" (Unsubscribes the user from this subscription type)
    }
  ],
  // To specify the Signup Source ID in the track event instead of destination setting
  // "signUpSourceId": 123456
  
  // For unsubscribe case:
  // Optional notification properties to override
  "notification": {
    "language": "en-US",
    "disable": true
  }
});
```

The above event results in the following `POST` calls:

- The `/subscriptions` endpoint is used for subscribing the user's `email` to the `email` channel.
- The `/subscriptions/unsubscribe` is used for unsubscribing `phone` from the `sms` channel.

For subscribing to both `email` and `sms` channels, you can send the channel consents as shown below:

```javascript
"channelConsents": [{
      "channel": "email",
      "consented": true
    },
    {
      "channel": "sms",
      "consented": true,
    }
 ]
```

#### Considerations

This section highlights some key considerations for the subscription and unsubscription operations.

##### **For subscription**

- [**Signup Source ID**]({{< ref "destinations/streaming-destinations/attentive-tag/setup-guide.md#connection-settings" >}}) is required for the subscription operation. You can also provide the `signUpSourceId` in the `track` event, as shown.

```javascript
rudderanalytics.track("subscription_event", {
  "context": {
    "traits": {
      "email": "alex@example.com",
      "phone": "+1-202-555-0146"
    }
  },
  "channelConsents": [{
    "channel": "email",
    "consented": true
  }],
  "signUpSourceId": 123456
});
```

{{< info >}}
The `signUpSourceId` field in the event payload overrides the **Signup Source ID** specified in the [destination settings]({{< ref "destinations/streaming-destinations/attentive-tag/setup-guide.md#connection-settings" >}}).
{{< /info >}}

##### **For unsubscription**

- The user is removed from **all subscriptions** if subscription `type` is not present in the event. 
- If `type` is provided, the user is removed from the specified subscription type or channel combination. An example is shown below:

```javascript
rudderanalytics.track("subscription_event", {
  "context": {
    "traits": {
      "email": "alex@example.com",
      "phone": "+1-202-555-0146"
    }
  },
  "channelConsents": [{
    "channel": "sms",
    "consented": false,
    "type": "MARKETING" // Unsubscribes the user from this subscription type
  }]
});
```

### Ecommerce events

RudderStack converts the following ecommerce events to the corresponding Attentive events:

| RudderStack event | Attentive event |
|:--------------------------------|:--------------------------|
| Product List Viewed <br /> Product Viewed | `product-view` |
| Product Added | `add-to-cart` |
| Order Completed | `purchase` |

#### Product List Viewed

RudderStack maps the `Product List Viewed` event properties to the following Attentive properties:

| RudderStack property | Attentive Tag property | 
|:--------------------------------|:--------------------------|
| `properties.products.$.product_id` <br/> <span style="color: #4D4DFF;font-size:12px;">Required </span> | `items.productId` | 
| `properties.products.$.price` <br/> <span style="color: #4D4DFF;font-size:12px;">Required </span> | `items.price.$.value` | 
| `properties.products.$.variant` <br/> <span style="color: #4D4DFF;font-size:12px;">Required </span> | `items.productVariantId` | 
| `traits.email`/`context.traits.email`/`properties.email`  | `user.email` | 
| `traits.phone`/`context.traits.phone`/`properties.phone`  | `user.phone` | 
| `externalId` | `user.externalIdentifiers` | 
| `properties.products.$.currency` | `items.price.$.currency` | 
| `properties.products.$.name` | `items.name` | 
| `properties.products.$.url` | `items.productUrl` | 
| `properties.products.$.image_url` | `items.productImage` | 
| `context.traits.customIdentifiers`/`traits.customIdentifiers` | `user.externalIdentifiers.customIdentifiers` | 

#### Product Viewed/Product Added

RudderStack maps the `Product Viewed` and `Product Added` event properties to the following Attentive properties:

| RudderStack property | Attentive property | 
|:--------------------------------|:--------------------------|
| `properties.product_id` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | `items.productId` |
| `properties.price` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span>| `items.price.$.value` |
| `properties.variant` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | `items.productVariant.Id` |
| `properties.currency` | `items.price.$.currency` | 
| `properties.name` | `items.name` |
| `properties.url` | `items.productUrl` |
| `properties.image_url` | `items.productImage` |
| `traits.email`/`context.traits.email`/`properties.email` | `user.email` | 
| `traits.phone`/`context.traits.phone`/`properties.phone` | `user.phone` | 
| `externalId` | `user.externalIdentifiers` | 
| `context.traits.customIdentifiers`/`traits.customIdentifiers` | `user.externalIdentifiers.customIdentifiers` | 

#### Order Completed

RudderStack maps the `Order Completed` event properties to the following Attentive properties:

| RudderStack property | Attentive property | 
|:--------------------------------|:--------------------------|
| `properties.products.$.variant` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span> | `items.productVariantId`  |  
| `properties.products.$.product_id` <br/> <span style="color: #4D4DFF;font-size:12px;">Required</span>| `items.productId` | 
| `properties.products.$.price` <br/> <span style="color: #4D4DFF;font-size:12px;">Required </span> | `items.price.$.value` | 
| `properties.products.$.currency` | `items.price.$.currency` | 
| `properties.products.$.name` | `items.name` | 
| `properties.products.$.url` | `items.productUrl` | 
| `properties.products.$.image_url` | `items.productImage` | 
| `traits.email`/`context.traits.email`/`properties.email`  | `user.email` | 
| `traits.phone`/`context.traits.phone`/`properties.phone`  | `user.phone` |
| `externalId` | `user.externalIdentifiers` | 
| `context.traits.customIdentifiers`/`traits.customIdentifiers` | `user.externalIdentifiers.customIdentifiers` | 

The following snippet highlights a sample `track` call for the above ecommerce event parameters:

```javascript
rudderanalytics.track("Order Completed", {
  "products": [{
    "product_id": "507f1f77bcf86cd799439011",
    "name": "MOBILE",
    "variant": "green",
    "price": "19",
    "image_url": "image.com",
    "url": "url.com",
    "quantity": "2",
    "currency": "USD"
  }]
}, {
  "traits": {
    "email": "alex@example.com",
    "phone": "+1-202-555-0146"
  },
  "externalId": [{
      "type": "clientUserId",
      "id": "144"
    },
    {
      "type": "shopifyId",
      "id": "224"
    },
    {
      "type": "klaviyoId",
      "id": "132"
    }
  ]
});
```
