# Twitter Destination

## Destination Info

* Accepts [Page](/docs/segment/connections/spec/page), [Track](/docs/segment/connections/spec/track) calls.
* Refer to it as **Twitter Ads** in the [Integrations object.](/docs/segment/guides/filtering-data/#filtering-with-the-integrations-object)

### Components

* [Browser](https://github.com/segment-integrations/analytics.js-integration-twitter-ads)

## Connection Modes

[Learn more about connection modes.](/docs/segment/connections/destinations/#connection-modes)

### Device-Mode

* web: yes
* mobile: no
* server: no

### Cloud-Mode

* web: no
* mobile: no
* server: no

[Our Twitter Ads destination code](https://github.com/segment-integrations/analytics.js-integration-twitter-ads) is all open-source on GitHub if you want to check it out.

## Getting Started

From your Segment Destinations page click on Twitter Ads. Twitter Ads can track conversions in two ways. You can opt to use their newest **Universal Website Tag** or their **Single Event Website Tag**. You could also use both types of tags on the same page.

If you want to use the universal tag, all you have to do is enter your **Universal Website Tag Pixel ID** in the settings and create your conversion events inside Twitter's UI. The **Universal Website Tag** will map to any Segment event listed in the table [Advanced Conversion Tracking/Dynamic Ads](#advanced-conversion-tracking-and-dynamic-ads). You can find this pixel ID in Twitter's snippet that is generated for you after making a new Universal Conversion Event:

![Code snippet for Twitter universal website tag with highlighted pixel ID placeholder.](https://docs-resources.prod.twilio.com/ca16cea8104703f689a934dc07a8d4f3e00e06b82d5c27e9ed713a0cae07c9aa.png)

If you'd like to use the **Single Event Website Tags**, you must map the Segment events to your tags' respective conversion pixel IDs. The **Single Event Website Tag** is good to use if your event names do not match the Segment supported events with the **Universal Website Tag**.

Note that Twitter Ads only works with Segment's client-side JavaScript library `analytics.js` as it requires its script or pixel to be loaded onto your website.

## Page

If you are using the **Universal Website Tag**, when you call `.page()` we will fire a standard pageview event using Twitter's JS library: `window.twq('track', 'PageView')` as seen in their auto generated snippet.

If you are only using **Single Event Website Tags**, we will load their standard pageview pixel with default query values (`revenue: 0, quantity: 0`) given that you have provided the **Page Pixel** in your Segment settings for Twitter Ads.

If you have both tags defined in your destination settings, we will load **both** the single event pixel as well as the use the universal JS library to send the pageview event.

## Track

### Single Event Website Tags

Each time you [`track`](/docs/segment/connections/spec/track) an event from the browser with our Twitter Ads destination enabled we compare the event name to the events you have mapped to **Twitter Conversion IDs** inside of Segment. If the event being tracked corresponds to a Twitter conversion, a Twitter conversion pixel will be loaded on that page with the ID that you mapped it to.

You can find your conversion pixel IDs after you create the single conversion event inside Twitter:

![Twitter Ads conversion event with highlighted Website Tag ID and unverified status.](https://docs-resources.prod.twilio.com/5653249de9bb0f16e8eacadc5170e421cb75bd6a3d77aa105d2fa3064f376342.png)

For example, if your mapping in Segment looks like this:

![Event mapping settings showing ABC event to Event Name and Attributes.](https://docs-resources.prod.twilio.com/e5f9dcfe5269d1e7c797ba84ece676d53f45070fb332b276abf57d2d91b6856c.png)

Then every time you make this [`track`](/docs/segment/connections/spec/track) call (from the browser):

```javascript
analytics.track('Signed Up', {
  quantity: 1,
  revenue: 10
});
```

We will fire a Twitter conversion pixel for you with a **Twitter Conversion ID** of `28j3fo`.

It doesn't matter what you call the conversion inside of Twitter Ads as long as you paste your **Twitter Conversion ID** next to the right event in Segment.

If you include `properties.quantity` and `properties.revenue` with your events, we will send that along as parameters of the conversion tag. If these two properties are not provided, we will send the two parameters as `0`.

Thus the example `.track()` event above would fire this tag:

```html
<img src="http://analytics.twitter.com/i/adsct?txn_id=28j3fo&p_id=Twitter&tw_sale_amount=10&tw_order_quantity=1">
```

### Advanced Conversion Tracking and Dynamic Ads

Our Twitter destination supports [Advanced Conversion Tracking](https://business.twitter.com/en/help/campaign-measurement-and-analytics/conversion-tracking-for-websites.html#advanced) which can be used to run **Dynamic Ads Campaigns**. Once you create your conversion events using **Universal Website Tag** inside Twitter's UI, just follow our [Ecommerce V2 Spec](/docs/segment/connections/spec/ecommerce/v2) and we will automatically map select events (listed below). Keep in mind that you **must** provide the **Universal Website Pixel ID** in your settings for this feature to work.

*NOTE*: *For each of these Segment events, we will still check if you had mapped any of them to a* **Single Event Website Tag** *in your Segment settings and fire those tags in addition to these advanced conversion tags.*

The following table shows which Segment events map to which type of Twitter tags:

| **Segment Event Name**    | **Twitter Tag Type** |
| ------------------------- | -------------------- |
| Order Completed           | Purchase             |
| Product Viewed            | ViewContent          |
| Product Added             | AddToCart            |
| Products Searched         | Search               |
| Product Added To Wishlist | AddToWishlist        |
| Checkout Started          | InitiateCheckout     |
| Payment Info Entered      | AddPaymentInfo       |

The following table show how the properties of Segment events would map to Twitter's supported parameters:

| **Segment Property Name**               | **Twitter Parameter** |
| --------------------------------------- | --------------------- |
| value / revenue / (price \* quantity)   | value                 |
| currency                                | currency              |
| products.$.product\_id / products.$.sku | content\_ids          |
| N/A                                     | content\_type         |
| products.$.name                         | content\_name         |
| products.$.category                     | content\_category     |
| products.$.quantity                     | num\_items            |
| order\_id                               | order\_id             |
| status                                  | status                |

**IMPORTANT**:

* You can choose in your Segment settings if you want to populate `content_ids` parameter with your `product_id`(s) or `sku`(s). Whatever you choose should match the IDs in your Product Feed if you are running dynamic ads.
* `content_type` will always be correctly hardcoded to be `'product'`.
* `content_name` and `content_category` for multiple products will be concatenated delimited by commas.
* `num_items` represents the sum total of all your products' respective quantities.
* While `properties.status` is not spec'd by Segment, you can still send that property through and we will map it to Twitter's `status` parameter, which is an optional free text field representing the state of the conversion event (eg. 'completed', 'in review', 'processed', etc.)
* `value`, `currency`, `order_id` and `num_items` will not be mapped for any pre-purchase tags because it will attribute revenue, which is undesired behavior for ecommerce/retail businesses.

The following code snippets represent the code Twitter would fire under the hood on your webpage given an example Segment event, and assumes that the setting for\* **Product Identifier** \*is `product ID` (it can also be SKU):

**Order Completed** -> **Purchase**

```js
analytics.track('Order Completed', {
  orderId: '50314b8e9bcf000000000000',
  total: 30,
  revenue: 25,
  shipping: 3,
  tax: 2,
  discount: 2.5,
  coupon: 'hasbros',
  currency: 'USD',
  repeat: true,
  products: [
    {
      product_id: '507f1f77bcf86cd799439011',
      sku: '45790-32',
      name: 'Monopoly: 3rd Edition',
      price: 19,
      quantity: 1,
      category: 'Games'
    },
    {
      product_id: '505bd76785ebb509fc183733',
      sku: '46493-32',
      name: 'Uno Card Game',
      price: 3,
      quantity: 2,
      category: 'Games'
    }
  ],
  status: 'completed!'
});
```

```js
window.twq('track', 'Purchase', {
  value: '25.00', // Required
  currency: 'USD', // Required. Defaults to 'USD'
  content_ids: ['505bd76785ebb509fc183733', '507f1f77bcf86cd799439011'], // Required
  content_type: 'product', // Required
  content_name: 'Monopoly: 3rd Edition, Uno Card Game',
  num_items: '3',
  order_id: '50314b8e9bcf000000000000',
  status: 'completed!'
});
```

**Product Viewed** -> **ViewContent**

```js
analytics.track('Product Viewed', {
  product_id: '507f1f77bcf86cd799439011',
  sku: 'G37',
  category: 'eSports',
  name: 'Starcraft: Brood War',
  brand: 'Blizzard',
  variant: 'Expansion Pack',
  price: 12.99,
  quantity: 2,
  coupon: 'STOPTHETILT',
  currency: 'USD',
  position: 1,
  value: 0.50
});
```

```js
window.twq('track', 'ViewContent', {
  content_ids: ['507f1f77bcf86cd799439011'], // Required
  content_type: 'product', // Required
  content_name: 'Starcraft: Brood War',
  content_category: 'eSports'
});
```

**NOTE**: *For this event, since `properties.value` is spec'd by Segment. we will respect that property over the `properties.price * properties.quantity` since the former can be a different explicit monetary value.*

**Product Added** -> **AddToCart**

```js
analytics.track('Product Added', {
  cart_id: 'yolo123',
  product_id: 'kenbone777',
  sku: '1',
  category: 'Political Action Figure',
  name: 'The Bone Zone',
  brand: 'Winner',
  variant: 'Original',
  price: 1738.00,
  quantity: 1,
  coupon: 'KENBONE',
  position: 1
});
```

```js
window.twq('track', 'AddToCart', {
  content_ids: ['kenbone777'], // Required
  content_type: 'product', // Required
  content_name: 'The Bone Zone'
});
```

**Products Searched** -> **Search**

```js
analytics.track('Products Searched', { query: 'gluten rich food' });
```

```js
window.twq('track', 'Search', {});
```

*NOTE*: *Since no parameters are required for this tag and its supported ones do not correspond with this spec'd event's properties, we will not map any properties for this tag other than `properties.status`.*

**Product Added To Wishlist** -> **AddToWishlist**

```js
analytics.track('Product Added to Wishlist', {
  wishlist_id: 'cmon-santa-bro',
  wishlist_name: 'This is the year',
  product_id: '507f1f77bcf86cd799439011',
  sku: 'G-32',
  category: 'TV Shows',
  name: 'Rick and Morty: Season 3',
  brand: 'Adult Swim',
  variant: 'DVD',
  price: 19.99,
  quantity: 1,
  coupon: 'RICKPOTION',
  position: 1
});
```

```js
window.twq('track', 'AddToWishlist', {
  content_name: 'Rick and Morty: Season 3',
  content_category: 'TV Shows',
  content_ids: ['507f1f77bcf86cd799439011']
});
```

**Checkout Started** -> **InitiateCheckout**

```js
analytics.track('Checkout Started', {
  order_id: '50314b8e9bcf000000000000',
  affiliation: 'Google Store',
  revenue: 25,
  shipping: 3,
  tax: 2,
  discount: 2.5,
  coupon: 'hasbros',
  currency: 'USD',
  products: [
    {
      product_id: '507f1f77bcf86cd799439011',
      sku: '45790-32',
      name: 'Monopoly: 3rd Edition',
      price: 19,
      quantity: 1,
      category: 'Games'
    },
    {
      product_id: '505bd76785ebb509fc183733',
      sku: '46493-32',
      name: 'Uno Card Game',
      price: 3,
      quantity: 2,
      category: 'Games'
    }
  ]
});
```

```js
window.twq('track', 'InitiateCheckout', {
  content_ids: ['505bd76785ebb509fc183733', '507f1f77bcf86cd799439011'],
  content_name: 'Monopoly: 3rd Edition, Uno Card Game',
  content_category: 'Games, Games'
});
```

**Payment Info Entered** -> **AddPaymentInfo**

```js
analytics.track('Payment Info Entered', {
  checkout_id: 'co-120387',
  order_id: '182hjdld9sl',
  step: 4,
  shipping_method: 'FedEx',
  payment_method: 'Credit Card'
});
```

```js
window.twq('track', 'AddPaymentInfo', {});
```

*NOTE*: *Since no parameters are required for this tag and its supported ones do not correspond with this spec'd event's properties, we will not map any properties for this tag.*

## Troubleshooting

### Script unverified or undetected by third-party tool

Many times this is a limitation on the tool's detection process, where the detector is looking for a specific HTML element on your page. Our client side analytics.js library asynchronously loads the tool's library or pixel onto the page. As such, the detection fails.

In order to confirm that the tool's library or pixel is actually loaded onto the page, you can open up the [JavaScript console](/docs/segment/connections/sources/catalog/libraries/website/javascript#how-do-i-open-the-javascript-console-in-your-debugger) and go to the network tab when the page is loading.

![Checking network tab to see if script loads.](https://docs-resources.prod.twilio.com/8a2cd023e90dc07c18494061e6013d19469548d2b7a40f6f4dba91417b7d6b39.gif)

If the script isn't loading, check that any form of ad blocker is disabled.

## Settings

Segment lets you change these destination settings from the Segment app without having to touch any code.

| Field                          | Description                                                                                                                                                                                                                                                                                                                     | Required | Type     |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------- |
| Events                         | Twitter recognizes pixel ids, not custom events. When you \`analytics.track(event, properties)\` an event that represents a Twitter conversion, you'll need to map the event name on the left to it's corresponding Twitter pixel id on the right. \[Contact us]\(https://segment.com/help/contact/) if you need help!          | No       | text-map |
| Product Identifier             | If you are using \[Advanced Conversion Tracking]\(https://business.twitter.com/en/help/campaign-measurement-and-analytics/conversion-tracking-for-websites.html), you can choose to send Product IDs or SKUs as the content\_ids. Whatever you choose should match the IDs in your Product Feed if you are running dynamic ads. | No       | select   |
| Page Pixel                     | Twitter recognizes pixel ids. This is just a special pixel id you can use for page views. It will get executed on any call to \`analytics.page()\`.                                                                                                                                                                             | No       | string   |
| Universal Website Tag Pixel ID | Twitter supports having a single universal website tag for conversions. Please enter your Universal Website Tag Pixel ID. This setting is also required in order to use \[Advanced Conversion Tracking]\(https://business.twitter.com/en/help/campaign-measurement-and-analytics/conversion-tracking-for-websites.html).        | No       | string   |
