> For the complete documentation index, see [llms.txt](https://help.citrusad.com/retail-media-interface/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.citrusad.com/retail-media-interface/integration/brand-pages/brand-page-retailer-integration-guide/tracking-attribution.md).

# Tracking & Attribution

## How to Compose a Tracking URL

The response provides three sources to combine:

* Page-level `trackers.impression`: for example, a page impression uses `type: "impression"` and `params` including `ts` and `iabConsentString`.
* Shared `trackingTemplates`: one set of `client`(relative) and `server` (absolute) URL templates, already containing session and placement query parameters.
* Per-node `trackers.click` and/or `trackers.addToCart` on a module, row, or gallery item: `type`+ `params` for that specific event (for example, `modId`, `rurl`, `productCode`).

### Which template?

Use the node’s `tracking.type` to look up `trackingTypes.<type>`. This defines the valid `client.*` and `server.*` keys for that interaction (for example, for link: `client.clickRedirect`, `client.clickEvent`, `server.clickEvent)`.

### Client vs Server

* Client (`trackingTemplates.client.*`): Values are relative paths (including query strings). Prepend your reverse‑proxy base URL (`BASEURL`).
* Server (`trackingTemplates.server.`): Values are absolute URL templates on the Epsilon tracking host. Compose the final URL the same way as C2S: template + `"&"` + `queryString(trackers.<slot>params)`.

{% hint style="info" %}
Do not change the template’s host or path, and do not send S2S calls through your reverse proxy.
{% endhint %}

### Worked examples (pseudocode)

#### C2S click for a HERO CTA

```
url = BASEURL + trackingTemplates.client.clickRedirect + "&" + queryString(trackers.click.params)
```

#### S2S page impression

```
url = trackingTemplates.server.impressionEvent + "&" + queryString(trackers.impression.params)
```

#### S2S add-to-cart for a product row

```
url = trackingTemplates.server.addToCartEvent + "&" + queryString(trackers.addToCart.params)
```

**Macro substitution**

* Replace {TS} with the current millisecond timestamp, {RURL} with the URL-encoded destination, and `{TCF}` with the current TCF v2 string from your CMP before firing.
* For add-to-cart, also substitute {QTY} with the absolute quantity of that SKU in the cart at fire time (not a delta), and {CONVERSION\_VALUE} with the absolute monetary value of those items (quantity × unit price, minus any applied discounts).

{% hint style="info" %}

* Only `trackingTemplates.client.impressionPixelUrls` are true pixels (1×1 GIFs).
  * `clickRedirect` is a 302 redirect endpoint.
  * `clickEvent` and `addToCartEvent` are event beacons that return 204 No Content.
    {% endhint %}

{% hint style="danger" %}
Do not fire both C2S and S2S for the same logical event (for example, do not send both a C2S click event and an S2S click notification for the same click).
{% endhint %}

## Tracking – Client‑to‑Server (C2S)

C2S tracking is implemented in the browser using composed URLs. Prepend `BASEURL` to the paths in `trackingTemplates.client` and append the appropriate `trackers.<slot>params` (see [How to Compose a Tracking URL](#how-to-compose-a-tracking-url)).

Only `client.impressionPixelUrls` are pixels (1×1 GIF). The other client templates are not pixels:

* `client.clickRedirect`: 302 redirect endpoint. Epsilon logs the click and redirects the browser to the decoded rurl. Use this as a browser navigation target.
* `client.clickEvent`: **Event beacon** returns 204 No Content). Fire using `navigator.sendBeacon` or `fetch({ keepalive: true })`. Do not render as `<img>`.
* `client.addToCartEvent`: **Event beacon** (returns 204). Uses the same firing pattern as `clickEvent`.

### Implementation Steps

1. Render the brand‑page content returned by the API.
2. After rendering, fire impression pixels in the browser (all entries in `trackingTemplates.client.impressionPixelUrls`, as 1×1 images).
3. When a user clicks a trackable node, either:\
   (a) redirect through the composed `client.clickRedirect` URL, or\
   (b) fire the composed `client.clickEvent` URL as an event beacon and navigate to the destination yourself.\
   Use one or the other per click, not both.

### Impression Pixel

After the brand page renders, fire each path in `trackingTemplates.client.impressionPixelUrls` as a 1×1 image, (see[ How to Compose a Tracking URL](#how-to-compose-a-tracking-url)).

```html
<img src="https://www.retailer.com/epsilon/tracking/v3/impression/pixel/brandpage_djog...?...&ts=1737485823910"
     width="1" height="1" style="display:none" />
```

**Steps:**

1. For each string in `trackingTemplates.client.impressionPixelUrls`, prepend your `BASEURL` (for example, `https://www.retailer.com/epsilon`).
2. Append `&` + `queryString(trackers.impression.params)`, substituting `{TS}` with the current millisecond timestamp and `{TCF}` with the current consent string from your CMP.
3. Fire as a 1×1 `< img src="...">` in the browser (or equivalent).

### Click Tracking

#### Option A: Click Redirect (`client.clickRedirect`)

Navigate the user through the composed URL. Epsilon logs the click and responds with **HTTP 302** to the decoded `rurl`. This endpoint is **GET only**, and `rurl` is required;

#### Option B: Click Event Beacon (`client.clickEvent`)

Fire as a beacon and navigate yourself. Accepts GET or POST, returns 204 No Content. Not an image; do not render as`<img>`.

### Add‑to‑Cart (C2S)

Fire `trackingTemplates.client.addToCartEvent` as an event beacon (not a pixel) when the user adds a product to cart. Accepts GET or POST, returns 204 No Content.

{% hint style="info" %}
Do not combine C2S and S2S add‑to‑cart for the same cart action.
{% endhint %}

## Tracking – Server‑to‑Server (S2S)

S2S tracking is implemented on your backend. Compose URLs the same way as C2S: start from the appropriate `trackingTemplates.server` string, then append `trackers.<slot>params`. Server templates are already absolute — there is no `BASEURL`to prepend. (see [How to Compose a Tracking URL](#how-to-compose-a-tracking-url)).

{% hint style="info" %}
Do not change the host or path from the server template, and do not send S2S requests through your reverse proxy.
{% endhint %}

### When to Use S2S Tracking

* Your architecture requires server‑side event firing.
* You need tracking in environments where client‑side pixels are unreliable.
* You want to mix strategies - e.g. C2S impressions + S2S add-to-cart. This is supported but never fire both C2S and S2S for the same event.

### S2S Impression Notification

After the brand page is rendered, your server issues a **GET** or **POST** to the composed impression URL: `trackingTemplates.server.impressionEvent` + `trackers.impression.params` (substitute `{TS}` and `{TCF}` before sending).

### S2S Click Notification

Compose: `trackingTemplates.server.clickEvent` + `trackers.click.params` (substitute `{TS}`, {RURL}, and `{TCF}`), then issue GET or POST.

### S2S Add-to-Cart Notification

Compose: `trackingTemplates.server.addToCartEvent` + `trackers.addToCart.params` (substitute `{TS}`, {QTY}, {CONVERSION\_VALUE}, and `{TCF}`), then issue GET or POST.

### S2S Parameters

| Parameter                                                                           | Source                            | Notes                                                                                                                                        |
| ----------------------------------------------------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `catalogId`, `sessionId`, `customerId`, `dtmId`, `placementId`, `lsid`, `utcOffset` | `trackingTemplates` query strings | Preserve these values as-is when firing the request. Do not remove or modify them.                                                           |
| `modId`                                                                             | `trackers.<slot>.params`          | Content module or row identifier.                                                                                                            |
| `ts`                                                                                | `trackers.<slot>.params`          | Replace `{TS}` with the current timestamp in milliseconds before firing the request.                                                         |
| `iabConsentString`                                                                  | `trackers.<slot>.params`          | Replace `{TCF}` with the current TCF v2 consent string from the CMP before firing the request. If a value is already provided, use it as-is. |
| `rurl`                                                                              | `trackers.<slot>.params`          | URL-encoded redirect destination. Replace `{RURL}` when present.                                                                             |
| `productCode`, `sellerId`                                                           | `trackers.<slot>.params`          | Values derived from product nodes.                                                                                                           |
| `qty`                                                                               | `trackers.addToCart.params`       | Replace `{QTY}` with the absolute quantity of the SKU in the cart at the time the request is fired. Do not use the quantity delta.           |
| `conVal`                                                                            | `trackers.addToCart.params`       | Replace `{CONVERSION_VALUE}` with the total monetary value of the items (quantity × unit price, minus any applicable discounts).             |

## Macro Reference

| Symbol                  | Description                                                                                                                 | Found In                                  | Substitute with                                                               |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ----------------------------------------------------------------------------- |
| `BASEURL` (your prefix) | Your site's base URL with protocol and proxy path - prepend to each `trackingTemplates.client.*` path.                      | C2S tracking                              | `https://www.retailer.com/epsilon`                                            |
| `{TS}`                  | Cache-busting timestamp (milliseconds)                                                                                      | `trackers.<slot>.params`                  | `1737485823910`                                                               |
| `{RURL}`                | URL-encoded redirect destination                                                                                            | `trackers.<slot>.params.rurl`             | `https%3A%2F%2Fwww.retailer.com%2Fprodukt%2F9221200653341`                    |
| `{TCF}`                 | IAB TCF v2 consent string placeholder. Present when `regs.consent` was omitted on the request.                              | `trackers.<slot>.params.iabConsentString` | Current TC string from your CMP, e.g. via `__tcfapi` `getTCData` → `tcString` |
| `{QTY}`                 | Absolute quantity of this SKU in the cart at fire time (not a delta; e.g. if the shopper had 1 and adds another, send `2`). | `trackers.addToCart.params.qty`           | `2`                                                                           |
| `{CONVERSION_VALUE}`    | Absolute monetary value of those items: quantity × unit price, minus any applied discounts.                                 | `trackers.addToCart.params.conVal`        | `49.99`                                                                       |
| `{RURL_KID}`            | Redirect signing key ID. Present in `trackers.click.redirectParams` when platform redirect signing is enabled.              | `trackers.click.redirectParams.rurlKid`   | Signing key id returned by the batch sign endpoint                            |
| `{RURL_SIG}`            | Redirect signing signature. Present in `trackers.click.redirectParams` when platform redirect signing is enabled.           | `trackers.click.redirectParams.rurlSig`   | Ed25519 signature (base64url) returned by the batch sign endpoint             |

### URL Encoding Reference

When encoding `{RURL}`, use standard percent-encoding:

| Character | Encode As |
| --------- | --------- |
| `:`       | `%3A`     |
| `/`       | `%2F`     |
| `?`       | `%3F`     |
| `=`       | `%3D`     |
| `&`       | `%26`     |

### redirectParams and Redirect Signing

When platform redirect signing is enabled, `trackers.click` may include a `redirectParams`object alongside `params`. The keys in `7`are merged only into `client.clickRedirect` URLs — not into `clickEvent`or any server URL.

Two cases:

**Embedded link destinations** (URL baked into `params.rurl`): the platform signs the redirect at serve time and emits literal `rurlKid`and `rurlSig`values in `redirectParams`. Append these as-is to the `clickRedirect` URL.

**Retailer-controlled redirects** (`params.rurl` is {RURL}): `redirectParams` contains the macros {RURL\_KID} and {RURL\_SIG}. Call the batch sign endpoint (`redirectSigning.url` from the response) to obtain the key id and signature for your destination URL, then substitute before appending.

The top-level `redirectSigning`object, when present, provides the batch `POST /ads/v3/redirect/sign` endpoint URL and the `maxUrls`batch limit. Contact Epsilon to confirm whether redirect signing is enabled for your integration.

### clickRedirect composition with redirectParams:

```
BASEURL + trackingTemplates.client.clickRedirect + "&" + queryString(trackers.click.params) + "&" + queryString(trackers.click.redirectParams)
```

<br>

## Style Guide

Before enabling Brand Pages on your site, we need to capture your site's visual identity. Fill in the table below with your design values. Our team will use this to configure the brand page preview experience.

#### Logo

| Field    | Description                        | Your Value |
| -------- | ---------------------------------- | ---------- |
| Logo URL | URL to your site logo (SVG or PNG) |            |

#### Colors

| Field                 | Description                                          | Your Value |
| --------------------- | ---------------------------------------------------- | ---------- |
| Primary Color         | Main brand color (hex)                               |            |
| Background Color      | Page background color (hex)                          |            |
| Surface Color         | Card/section background color (hex)                  |            |
| Primary Text Color    | Main text color (hex)                                |            |
| Secondary Text Color  | Muted text color (hex)                               |            |
| Text on Primary Color | Text color used on primary-colored backgrounds (hex) |            |
| Border Color          | Default border color (hex)                           |            |

#### Typography

| Field               | Description                                             | Your Value |
| ------------------- | ------------------------------------------------------- | ---------- |
| Heading Font Family | Font used for headings (e.g. "Google Sans, sans-serif") |            |
| Body Font Family    | Font used for body text (e.g. "Roboto, sans-serif")     |            |
| Base Font Size      | Default body font size (e.g. 16px)                      |            |

#### Buttons

| Field                        | Description                                                 | Your Value |
| ---------------------------- | ----------------------------------------------------------- | ---------- |
| Primary Button Background    | Background color for primary buttons                        |            |
| Primary Button Text Color    | Text color for primary buttons                              |            |
| Primary Button Border Radius | Corner rounding (e.g. 8px)                                  |            |
| Secondary Button Style       | Describe secondary button appearance (outline, ghost, etc.) |            |

## Module Content Requirements

Brand Pages are composed of content modules. For each module type, provide the content constraints your site requires. Our team will use these to configure template validation rules.

### IMAGE Modules

| Requirement            | Description                                               | Your Value |
| ---------------------- | --------------------------------------------------------- | ---------- |
| Min Width              | Minimum image width in pixels (e.g. 1920)                 |            |
| Min Height             | Minimum image height in pixels (e.g. 500)                 |            |
| Max File Size          | Maximum file size in MB (e.g. 10). Must be less than 4MB. |            |
| Accepted Formats       | Accepted image formats (e.g. jpg, png, gif, svg)          |            |
| Caption Max Characters | Max characters for image caption, if applicable           |            |
| `alt`tag optionality   | Whether `alt` is required on images.                      |            |

### TEXT Modules

| Requirement                | Description                                                                                                                                                                                                                                            | Your Value |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- |
| Variant                    | “headline”, “tagline”, “body”, or “lines”. Determines the style in which the text is displayed.                                                                                                                                                        |            |
| Alignment                  | “left”, “center”, or “right”. Determines the horizontal alignment of the text.                                                                                                                                                                         |            |
| “Lines” configuration      | <p>Configuration for multi-line text configuration (when variant = lines). For each line of text, provide the following:<br><br>- name of the text field<br>- “required” or “allowed”?<br>- whether this is meant to be a hyperlink to another URL</p> |            |
| Headline Max Characters    | Max characters for headline text                                                                                                                                                                                                                       |            |
| Description Max Characters | Max characters for description text                                                                                                                                                                                                                    |            |
| Body/Footer Max Characters | Max characters for body or footer text                                                                                                                                                                                                                 |            |
| CTA Button                 | Required, optional, or not needed?                                                                                                                                                                                                                     |            |
| CTA Text Max Characters    | Max characters for CTA button label                                                                                                                                                                                                                    |            |

### PRODUCT\_GRID Modules

| Requirement                        | Description                                     | Your Value |
| ---------------------------------- | ----------------------------------------------- | ---------- |
| Min Products                       | Minimum number of products to display (e.g. 4)  |            |
| Max Products                       | Maximum number of products to display (e.g. 12) |            |
| Section Title                      | Required or optional?                           |            |
| Section Title Max Characters       | Max characters for section title                |            |
| Section Description                | Required or optional?                           |            |
| Section Description Max Characters | Max characters for section description          |            |
| CTA Button                         | Required, optional, or not needed?              |            |

### IMAGE\_GALLERY Modules

The Image Gallery module inherits the same configuration properties as the IMAGE module. Additionally, it also accepts the following gallery-specific properties:

| Requirement                | Description                                                                                                                                                                                                                                             | Your Value |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| Min Images                 | Minimum number of gallery images (e.g. 2)                                                                                                                                                                                                               |            |
| Max Images                 | Maximum number of gallery images (e.g. 4)                                                                                                                                                                                                               |            |
| Section Title              | Whether the section title text is required or optional.                                                                                                                                                                                                 |            |
| Section Description        | Whether the section description text is required or optional.                                                                                                                                                                                           |            |
| `alt` tag optionality      | Whether `alt` is required on images.                                                                                                                                                                                                                    |            |
| Call-to-action optionality | Whether the call-to-action button or link is required, allowed, or disabled.                                                                                                                                                                            |            |
| Additional Text Lines      | <p>For each additional text that is to be associated with each image in the image gallery, provide the following:<br><br>- name of the text field<br>- “required” or “allowed”?<br>- whether the text should function as a hyperlink to another URL</p> |            |

### SPLIT\_LAYOUT Modules

The Split Layout module allows two modules to be displayed side by side. Currently, only Text and Image modules are supported. In addition to the individual configuration settings for the Text and Image modules (described in the sections above), the following additional properties are required:

| Requirement  | Description                           | Your Value |
| ------------ | ------------------------------------- | ---------- |
| Layout Ratio | Column ratio (50:50, 33:67, or 67:33) |            |

## Identity and Privacy

### Acceptable Identifiers

* Session ID - anonymous session identifier (non-PII)
* Customer ID - retailer customer identifier (non-PII, e.g. loyalty ID hash)

{% hint style="danger" %}
Do not pass hashed email addresses, phone numbers, or any PII in any parameter or URL.
{% endhint %}

### Privacy Requirements

Retailers must:

* Disclose measurement tracking in their privacy policy
* Provide opt-out links:
  * NAI: <https://optout.networkadvertising.org/>
  * DAA: <https://optout.aboutads.info/>

### GDPR / Consent

Pass the `regs`object on `POST /ads/v3/brand-pages`:

* `regs.gdpr`: `1` when the request is subject to GDPR (EU/EEA/UK treatment per your policy); `0`otherwise.
* `regs.consent`: When `gdpr` is `1`, pass the current TCF v2 consent string from your CMP (the same value you would surface to other ad partners). Do not invent or hardcode a string—use what the user’s browser / app has consented to.
* `iabConsentString`: This appears in every tracker slot's params, not in `trackingTemplates`. When `regs.consent` was provided, the value is the literal TC string and no further action is needed.
* When `regs.consent` was omitted, the value is the `{TCF}`macro — substitute the current TCF v2 string from your CMP at fire time before sending any tracking request.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://help.citrusad.com/retail-media-interface/integration/brand-pages/brand-page-retailer-integration-guide/tracking-attribution.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
