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).
📘

Do not change the template’s host or path, and do not send S2S calls through your reverse proxy.

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).
📘
  • 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.
❗️

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).

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).

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).

<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.

📘

Do not combine C2S and S2S add‑to‑cart for the same cart action.

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 BASEURLto prepend. (see How to Compose a Tracking URL).

📘

Do not change the host or path from the server template, and do not send S2S requests through your reverse proxy.

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

ParameterSourceNotes
catalogId, sessionId, customerId, dtmId, placementId, lsid, utcOffsettrackingTemplates query stringsPreserve these values as-is when firing the request. Do not remove or modify them.
modIdtrackers.<slot>.paramsContent module or row identifier.
tstrackers.<slot>.paramsReplace {TS} with the current timestamp in milliseconds before firing the request.
iabConsentStringtrackers.<slot>.paramsReplace {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.
rurltrackers.<slot>.paramsURL-encoded redirect destination. Replace {RURL} when present.
productCode, sellerIdtrackers.<slot>.paramsValues derived from product nodes.
qtytrackers.addToCart.paramsReplace {QTY} with the absolute quantity of the SKU in the cart at the time the request is fired. Do not use the quantity delta.
conValtrackers.addToCart.paramsReplace {CONVERSION_VALUE} with the total monetary value of the items (quantity × unit price, minus any applicable discounts).

Macro Reference

SymbolDescriptionFound InSubstitute with
BASEURL (your prefix)Your site's base URL with protocol and proxy path - prepend to each trackingTemplates.client.* path.C2S trackinghttps://www.retailer.com/epsilon
{TS}Cache-busting timestamp (milliseconds)trackers.<slot>.params1737485823910
{RURL}URL-encoded redirect destinationtrackers.<slot>.params.rurlhttps%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.iabConsentStringCurrent TC string from your CMP, e.g. via __tcfapi getTCDatatcString
{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.qty2
{CONVERSION_VALUE}Absolute monetary value of those items: quantity × unit price, minus any applied discounts.trackers.addToCart.params.conVal49.99
{RURL_KID}Redirect signing key ID. Present in trackers.click.redirectParams when platform redirect signing is enabled.trackers.click.redirectParams.rurlKidSigning 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.rurlSigEd25519 signature (base64url) returned by the batch sign endpoint

URL Encoding Reference

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

CharacterEncode As
:%3A
/%2F
?%3F
=%3D
&%26

redirectParams and Redirect Signing

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

Two cases:

Embedded link destinations (URL baked into params.rurl): the platform signs the redirect at serve time and emits literal rurlKidand rurlSigvalues 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 redirectSigningobject, when present, provides the batch POST /ads/v3/redirect/sign endpoint URL and the maxUrlsbatch 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)

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

FieldDescriptionYour Value
Logo URLURL to your site logo (SVG or PNG)

Colors

FieldDescriptionYour Value
Primary ColorMain brand color (hex)
Background ColorPage background color (hex)
Surface ColorCard/section background color (hex)
Primary Text ColorMain text color (hex)
Secondary Text ColorMuted text color (hex)
Text on Primary ColorText color used on primary-colored backgrounds (hex)
Border ColorDefault border color (hex)

Typography

FieldDescriptionYour Value
Heading Font FamilyFont used for headings (e.g. "Google Sans, sans-serif")
Body Font FamilyFont used for body text (e.g. "Roboto, sans-serif")
Base Font SizeDefault body font size (e.g. 16px)

Buttons

FieldDescriptionYour Value
Primary Button BackgroundBackground color for primary buttons
Primary Button Text ColorText color for primary buttons
Primary Button Border RadiusCorner rounding (e.g. 8px)
Secondary Button StyleDescribe 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

RequirementDescriptionYour Value
Min WidthMinimum image width in pixels (e.g. 1920)
Min HeightMinimum image height in pixels (e.g. 500)
Max File SizeMaximum file size in MB (e.g. 10). Must be less than 4MB.
Accepted FormatsAccepted image formats (e.g. jpg, png, gif, svg)
Caption Max CharactersMax characters for image caption, if applicable
alttag optionalityWhether alt is required on images.

TEXT Modules

RequirementDescriptionYour 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” configurationConfiguration for multi-line text configuration (when variant = lines). For each line of text, provide the following:
  • name of the text field
  • “required” or “allowed”?
  • whether this is meant to be a hyperlink to another URL
Headline Max CharactersMax characters for headline text
Description Max CharactersMax characters for description text
Body/Footer Max CharactersMax characters for body or footer text
CTA ButtonRequired, optional, or not needed?
CTA Text Max CharactersMax characters for CTA button label

PRODUCT_GRID Modules

RequirementDescriptionYour Value
Min ProductsMinimum number of products to display (e.g. 4)
Max ProductsMaximum number of products to display (e.g. 12)
Section TitleRequired or optional?
Section Title Max CharactersMax characters for section title
Section DescriptionRequired or optional?
Section Description Max CharactersMax characters for section description
CTA ButtonRequired, 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:

RequirementDescriptionYour Value
Min ImagesMinimum number of gallery images (e.g. 2)
Max ImagesMaximum number of gallery images (e.g. 4)
Section TitleWhether the section title text is required or optional.
Section DescriptionWhether the section description text is required or optional.
alt tag optionalityWhether alt is required on images.
Call-to-action optionalityWhether the call-to-action button or link is required, allowed, or disabled.
Additional Text LinesFor each additional text that is to be associated with each image in the image gallery, provide the following:
  • name of the text field
  • “required” or “allowed”?
  • whether the text should function as a hyperlink to another URL

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:

RequirementDescriptionYour Value
Layout RatioColumn 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)
❗️

Do not pass hashed email addresses, phone numbers, or any PII in any parameter or URL.

Privacy Requirements

Retailers must:

GDPR / Consent

Pass the regsobject on POST /ads/v3/brand-pages:

  • regs.gdpr: 1 when the request is subject to GDPR (EU/EEA/UK treatment per your policy); 0otherwise.
  • 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.