---
title: Dotdigital (Tag)
slug: dotdigital-tag
docTags: 
createdAt: 2026-09-14T18:29:15.581Z
---

Dotdigital is a marketing automation platform for email, SMS and cross-channel programs. The Dotdigital Tag destination loads Dotdigital in the browser and feeds it your Chord events, so it can track web behaviour, recover abandoned browses and abandoned carts, and report orders.

This is the surface that makes abandonment work. Dotdigital's abandoned-cart program starts its timer from the last cart update it saw in the browser, and abandoned browse depends on the visitor session the Tag establishes — neither can be driven from a server. For contact data fields, address book membership and consent records, pair this with the [Dotdigital](#) destination.

# Getting Started

You need one value, and one thing removed.

**Your Tag URL.** In Dotdigital go to **Connect > Connect website**, select **View code**, and copy the `src` value out of the script tag. It looks like `https://r1.ddlnk.net/DM-0000000000-01/ddgtag`, or `https://emails.yourbrand.com/DM-0000000000-01/ddgtag.js` if your account uses a branded domain. Dotdigital generates this per account, so use the one your account shows rather than adapting an example — the host varies, and it is the host your storefront's Content Security Policy has to allow.

**Remove any Dotdigital Tag you installed yourself**, including one added through a commerce-platform app. This is not a preference: two tags on one page create two sessions, double every page view, and split one shopper's behaviour across both. This destination replaces that installation rather than complementing it.

Three settings are optional but worth filling in:

- **Abandoned Cart Delay** and **Abandoned Cart Program ID** — how long Dotdigital waits after the last cart update, and which program to enrol into. Find the program ID in the URL when you open it under **Automation > Programs**. Without them Dotdigital applies your account defaults.
- **Cart URL** — your storefront's cart page. Required. Dotdigital rejects a cart update unless *every line* carries a product URL, and this is what Chord falls back to for a line that has none, so leaving it empty stops cart tracking working at all. It is also the link a shopper follows out of an abandoned cart email.
- **Site Brand** — only if your account uses Dotdigital Personalization.

# Connecting to the Dotdigital CDP Destination

:::BlockQuote
**Warning:** Before connecting destinations in the Chord CDP, please verify with all Destination owners that all **non-Chord CDP** configured destinations are **disabled**. Running external destinations alongside configured Chord CDP destinations **can result in duplicate events downstream.**
:::

1. Log into the Chord data platform.
2. Navigate to the CDP.
3. Click the **"Add"** button next to Destinations.
4. Select **Dotdigital Tag** from the destination catalog.
5. Enter the destination name and your **Tag URL**, plus any of the optional settings above.
6. Click **"Create"** to connect.
7. Connect it to your **front-end** site.
8. Remove your own Dotdigital Tag from the storefront.

# Using Alongside the Dotdigital Destination

The [Dotdigital](#) destination talks to Dotdigital's v3 API server-side. The two are complementary rather than duplicates, and both can run on the same Dotdigital account:

- **This destination** owns web behaviour tracking, abandoned browse and abandoned cart. None of that is reproducible server-side.
- **The Dotdigital destination** owns the contact record — data fields, address book membership, consent records — which this destination's identify call cannot write. It is also unaffected by ad blockers.

**One thing to know before you enable both: order and cart data lands in two places.** This destination writes into Dotdigital's own order and cart collections — the ones its abandoned-cart program and its order content blocks read. Dotdigital's Events API is not permitted to write into those same collections, so when the server-side destination reports an order it creates a separate, generically-named Insight data collection instead.

That is not double-counting in Dotdigital's order reporting, but it does mean an order reported by both surfaces exists as two records in two collections. If you segment or build content on order data, decide which surface is your source of truth and use that collection. If you only want one, this destination is the one to keep for abandonment, and the server-side destination is the one to keep if reliability against ad blockers matters more.

# Deduplication

Custom events carry a `messageId` attribute — a unique identifier for that event. If you also push events into the same Dotdigital account from another system, that is the value to deduplicate against.

Commerce calls are different, and the limitation is Dotdigital's rather than Chord's: `cartUpdate`, `checkout` and `purchaseComplete` accept no per-call event identifier. The order's own `orderId` and the cart's `cartId` are the only handles available, and **Dotdigital does not document deduplicating on either** — it describes them only as unique identifiers. So treat "report each order once" as the rule rather than relying on Dotdigital to sort out a repeat. Chord skips an `Order Completed` that carries no `order_id` for the same reason: an order with no reference cannot be deduplicated or reconciled by anyone.

# Event Mapping

| Chord event                                               | Dotdigital                                          |
| --------------------------------------------------------- | --------------------------------------------------- |
| `Page Viewed`                                             | Page view                                           |
| `Product Viewed`                                          | Product browse                                      |
| `Product List Viewed`                                     | Product list                                        |
| `Product Added`, `Product Removed`, `Cart Viewed`         | Cart update                                         |
| `Checkout Started`                                        | Checkout                                            |
| `Order Completed`                                         | Purchase, with the order reference and cart         |
| `identify`, `Email Captured`, `Signed Up`, `User Created` | Contact identification                              |
| Any other `track` event                                   | Custom event under its own name — see Custom Events |

# Product and Cart Data

Dotdigital uses two different product shapes, and Chord sends the right one for each call.

**Product browse and product list** send:

| Chord event property                | Dotdigital field                   |
| ----------------------------------- | ---------------------------------- |
| `product_id`                        | `productId`                        |
| `sku`                               | `sku`                              |
| `name`                              | `name`                             |
| `url`, falling back to the page URL | `url`                              |
| `image_url`                         | `imageUrl` and `imageThumbnailUrl` |
| `price`                             | `price`                            |
| `currency`                          | `currency`                         |
| `brand`                             | `brand`                            |
| `category`                          | `categories`                       |
| `description`                       | `description`                      |
| `variant_id`                        | `variantId`                        |

`imageThumbnailUrl` is filled from the same image as `imageUrl` because Chord's tracking plan carries one product image. Dotdigital's default content blocks read the thumbnail, so an empty one renders a blank image in a browse-abandonment email.

**Cart lines** send:

| Chord event property                                                                              | Dotdigital field |
| ------------------------------------------------------------------------------------------------- | ---------------- |
| `product_id`                                                                                      | `productId`      |
| `sku`, falling back to `variant_id` then `product_id`                                             | `sku`            |
| `name`                                                                                            | `name`           |
| `price`                                                                                           | `price`          |
| `quantity`                                                                                        | `quantity`       |
| `price` × `quantity`                                                                              | `totalPrice`     |
| `image_url`                                                                                       | `imageUrl`       |
| `url`, falling back to the event's `url` for the line that changed, then the **Cart URL** setting | `url`            |
| `brand`                                                                                           | `brand`          |
| `category`                                                                                        | `categories`     |
| `variant_id`                                                                                      | `variantId`      |

**Cart totals** send:

| Chord event property                                   | Dotdigital field |
| ------------------------------------------------------ | ---------------- |
| `cart_id`, falling back to `order_id` or `checkout_id` | `cartId`         |
| `currency`                                             | `currency`       |
| `subtotal`, falling back to the sum of the line totals | `subtotal`       |
| `total`                                                | `grandTotal`     |
| `cart_url`, falling back to the **Cart URL** setting   | `cartUrl`        |
| `shipping`                                             | `shipping`       |
| `discount`                                             | `discountAmount` |
| `tax`                                                  | `taxAmount`      |

A product line with no resolvable product ID is dropped rather than sent blank, because Dotdigital keys its catalogue and its abandonment content off the product ID.

## Fields Dotdigital requires

Dotdigital rejects a call outright when any of these is missing, and Chord's tracking plan marks them optional. Chord fills each one so your events are not refused, but **the substituted value is a fallback, not your data** — send the real one and it is always preferred.

| Field                        | Substituted with                                                        | What you lose by relying on it                                                                                                                                                                                                                              |
| ---------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Product `url` on a browse    | The URL of the page the event fired on                                  | Nothing, normally. On a `Product Viewed` the page *is* the product's page.                                                                                                                                                                                  |
| Product `url` on a cart line | The event's own `url` for the line that changed, then your **Cart URL** | Every other line links to your cart page instead of its product. The shopper still returns to their basket, but not to the item they were looking at.                                                                                                       |
| `sku` on a cart line         | `variant_id`, then `product_id`                                         | If your Dotdigital catalogue is keyed on real SKUs, the line will not match a catalogue entry, so merchandising blocks in your emails have nothing to render.                                                                                               |
| Cart `subtotal`              | The sum of the line totals                                              | Nothing, normally — it is arithmetic on the lines you sent, and excludes tax and shipping exactly as Dotdigital's own subtotal does. If no line carries a price, Chord sends no subtotal and Dotdigital refuses the cart, rather than reporting it as free. |

**Sending&#x20;**`sku`**&#x20;and&#x20;**`url`**&#x20;on your cart lines is worth the effort.** They are the two whose fallbacks change what a shopper sees in an email. Note that Chord's tracking plan currently documents a product `url` at the event level but not inside the `products` array — so per-line URLs are something to add to your event payload deliberately.

**Every cart update sends your whole basket, not just the line that changed.** Dotdigital's cart update *replaces* the cart it has stored, and its abandonment timer runs against that. So if your `Product Added` event carries a `products` array, Chord sends all of it. Send the full basket on those events, or Dotdigital's cart will be narrower than your shopper's.

A cart update with no `cart_id` is skipped, because Dotdigital tracks abandonment against the cart identifier and a cart with no stable ID looks like a new abandoned cart on every change.

# Identity

Dotdigital receives the email address, mobile number and name **in plaintext**, and this is deliberate. Dotdigital has to actually deliver mail and SMS to the person, so unlike an advertising pixel it accepts no hashed identifier — hashing would break delivery rather than protect anything. If your security review needs to know exactly what leaves the page, that is the list.

| Chord trait                | Dotdigital field |
| -------------------------- | ---------------- |
| `email`                    | `email`          |
| `phone`                    | `mobileNumber`   |
| `first_name`               | `firstName`      |
| `last_name`                | `lastName`       |
| `first_name` + `last_name` | `fullName`       |

**Mobile numbers must be in E.164 format** — `+14155550123`. A number with no country code is skipped rather than guessed at: completing it would mean assuming a country, and a wrong assumption can resolve to a real contact somewhere else and send them someone else's messages. Formatting like spaces, dashes and brackets is fine; a leading `00` is treated the same as `+`.

An identify with neither an email nor a valid E.164 mobile number is skipped, since Dotdigital has no contact to attach it to.

The name fields are Personalization-only. Dotdigital's Marketing platform ignores them, so they matter only if your account uses Personalization.

# Custom Events

Dotdigital's event taxonomy is **open**: an event Chord has no specific mapping for is forwarded under its own name, and Dotdigital creates an Insight data collection for it. `Loyalty Tier Changed` becomes a `Loyalty_Tier_Changed` collection — Dotdigital replaces non-alphanumeric characters with underscores when it names the collection.

Two limits:

- **Custom events need the CXDP package** on your Dotdigital account. Without it Dotdigital cannot accept them, and because the Tag's calls are fire-and-forget the rejection is invisible from the page. Turn **Send Custom Events** off if your account does not have CXDP. Turning it off does not affect any of the mapped commerce events.
- **Nine collection names are reserved** by Dotdigital for its own features: `cartInsight`, `catalog`, `consentInsight`, `easyEditorExtensions`, `nostoEmailCampaigns`, `orders`, `productCategories`, `webInsight` and `wishList`. An event whose name matches one of those is skipped, and the reason is logged to the browser console.

# Property Mappings

You can map any event property onto a destination field from the connection's mapping configuration. Mapped properties use a **bare path** on this destination — `properties.customer_type → customer_type`, with no `properties.` prefix on the destination side.

**Mapped properties reach custom events only.** They are forwarded as attributes on the custom-event call, and nowhere else. That is a Dotdigital constraint rather than a Chord choice: `identify`, the product calls and every cart call take a fixed set of fields with no property bag anywhere, so an extra key has nowhere to go. A mapping you configure will not appear on a product view, a cart update or an order.

Mapping onto a field Dotdigital *does* accept still works — a mapping that rewrites `properties.sku` changes what Chord reads for the product's `sku`, because mappings are applied before the payload is built. It is only destination keys with no Dotdigital equivalent that have nowhere to land.

Personal fields — `email`, `phone`, `first_name`, `last_name` and their camelCase forms — are never forwarded as custom attributes. They go through the identification call above instead.

# Content Security Policy

If your storefront sets a Content Security Policy, the Dotdigital Tag will not load until its hosts are allowed. The symptom is silence: no tracking, no abandonment, and a `Refused to load` or `Refused to connect` message in the browser console.

**The first host to allow is the one in your own Tag URL, and it is account-specific.** Dotdigital serves the Tag from `ddlnk.net` for some accounts and from a domain of your own for others — an account configured with a branded sending domain gets a Tag URL like `https://emails.yourbrand.com/DM-0000000000-01/ddgtag.js`. Read the host off the **Tag URL** you pasted into the destination and allow that one, rather than assuming the table below covers you.

| Directive     | Host                                                                               |
| ------------- | ---------------------------------------------------------------------------------- |
| `script-src`  | the host from your Tag URL, plus `https://*.ddlnk.net`                             |
| `connect-src` | the host from your Tag URL, plus `https://*.ddlnk.net`, `https://*.trackedweb.net` |

Both directives are required. `script-src` lets the Tag load; `connect-src` lets it report — and a policy that allows only the first fails in a way that looks like it worked, because the script runs and nothing reaches Dotdigital.

**This list was confirmed on a live account**, with one addition worth knowing: the account tested had a branded domain, and its Tag URL host had to be allowed in `script-src` on top of the two Dotdigital domains. That host differs per account, which is why it cannot be listed here.

Dotdigital does not publish its CSP requirements, and the Tag routes to a regional host at runtime, so treat the table as a starting point rather than a complete list. Verify it during setup: load a page with the destination active, then fire a product view, a cart update and an order, and add any host named in a violation. Check the Network tab as well as the console — a blocked image beacon can be quieter than a blocked script.

# Gotchas

**Two tags is the most common problem.** If page views look doubled or abandonment fires against a cart that does not match, check whether a hand-installed Dotdigital Tag or a platform app is still on the page.

**Dotdigital's calls are fire-and-forget.** They return nothing and throw nothing, by design, so a rejected call does not surface on the page. To confirm a call succeeded, inspect the request in your browser's Network tab: a `200` means Dotdigital accepted it, a `4xx` means something is misconfigured.

**Cart abandonment needs a cart update on every page.** Dotdigital's timer runs from the last cart update it saw, so a storefront that only reports the cart on the cart page will trigger abandonment early. Fire a cart-bearing event as the shopper continues browsing.

**An empty&#x20;**`Order Completed`**&#x20;is skipped.** An order event with no products is not sent, because it would write an empty order into the collection your post-purchase programs and order content blocks read — an email with nothing in it.

**Consent gating applies.** If the destination is configured with required consent categories, no Dotdigital call is made for visitors who have not accepted them.

**Updated 9 September 2026**
