Exactag
Datafly Signal delivers events to Exactag server-to-server using the Exactag S2S Tracking API. Page impressions and onsite conversions are sent directly from your Signal deployment to Exactag’s tracking endpoint, feeding Exactag’s multi-touch attribution (MTA), marketing-mix modelling, and customer-lifetime-value analysis without relying on a browser pixel.
Prerequisites
Before configuring Exactag in Signal you need an active Exactag account and your brand-specific campaign code.
Get your Exactag campaign code
Exactag issues a 32-byte encrypted, brand-specific campaign code during onboarding. It identifies your brand to the S2S endpoint and authorises tracking.
- Contact your Exactag account manager or technical contact.
- Request the S2S Tracking campaign code for the brand you want to track.
- Confirm with Exactag which sitegroup values map to page impressions versus conversions for your account — these are configured per brand on the Exactag side.
Confirm your tracking model
Exactag attributes conversions across the full customer journey. Make sure you can supply a stable first-party identifier (Signal provides this automatically as anonymous_id) and, for conversions, an order ID and basket value.
Configuration
| Field | Required | Description |
|---|---|---|
campaign_code | Yes | Your 32-byte encrypted, brand-specific Exactag campaign code. Provided by Exactag during onboarding. Treat it as a credential. |
Configure in Signal
- In the Management UI, go to Integrations > Add Integration > Exactag.
- Choose the Default preset (page impressions plus onsite conversions).
- Enter your
campaign_code. - Select the consent categories that gate this integration (typically
marketingoradvertising). - Click Save.
API Endpoint
GET https://m.exactag.com/s2s/pi.ashx?campaign={campaign_code}&sitegroup={event}&...All fields are sent as URL query-string parameters. The campaign parameter carries your campaign code, and the sitegroup parameter distinguishes the event type (page impression vs conversion). Signal forwards the original visitor’s IP and User-Agent as request headers so Exactag’s server-side resolution attributes the real user rather than the Signal worker.
Identity Signals
Exactag matches events to a customer journey using a first-party user key plus request context.
| Signal | Exactag field | Description |
|---|---|---|
anonymous_id | euk | First-party user key. Sent automatically by Signal as a stable cross-session identifier. |
| IP address | ipaddress | Visitor’s IP, forwarded from the original request. |
| User-Agent | useragent | Visitor’s User-Agent, forwarded from the original request. |
| Session ID | sessionid | Identifies a single user session. |
| Session number | sescount | 1 for a new visitor, greater than 1 for a returning visitor. |
| First-in-session flag | sesevent | 1 for the first impression in a session. |
| Customer ID | customerid | The identified user ID (sent on conversions for cross-device attribution). |
No raw PII is sent to Exactag by this blueprint. Identity is carried by Signal’s first-party anonymous_id (euk) and, on conversion, your own customerid. If your Exactag account expects a hashed Exactag User ID (uk) instead of a first-party key, adjust the field mapping in the Management UI.
Consent
Marketing consent from your CMP is mapped to Exactag’s privacy fields:
| Signal source | Exactag field | Behaviour |
|---|---|---|
context.consent.canonical.marketing | optout | 0 when marketing consent is granted, 1 (opt-out) otherwise. |
context.consent.tcf_string | consent_string | The IAB TCF v2 consent string, when present. |
Event Mapping
The Default preset maps Signal’s GA4-style events to Exactag sitegroups:
| Signal event | Exactag sitegroup |
|---|---|
page | pageview |
Products Searched | pageview (with search) |
Product Viewed | pageview |
Order Completed | conversion |
The pageview and conversion sitegroup values are defaults. Exactag configures the exact sitegroup codes per brand — confirm yours with Exactag and update the event mappings in the Management UI to match.
Example: Conversion Event
Datafly.js call:
datafly.track("Order Completed", {
order_id: "ORD-001",
revenue: 129.99,
affiliation: "web"
});Exactag request sent by Signal:
GET https://m.exactag.com/s2s/pi.ashx
?campaign=YOUR_CAMPAIGN_CODE
&version=1.0
&sitegroup=conversion
&euk=a1b2c3d4e5f6...
&sessionid=sess_789
&sescount=2
&sesevent=0
&referrer=https%3A%2F%2Fexample.com%2Fcheckout
&orderid=ORD-001
&totalprice=129.99
&customerid=user-123
&level=web
&optout=0(ipaddress and useragent are forwarded as the X-Forwarded-For and User-Agent request headers rather than query parameters.)
Exactag’s S2S endpoint does not document a separate currency parameter — totalprice is the basket value in your account’s configured currency. If you need to send currency explicitly, add it inside the params JSON field via a Management UI mapping and confirm the shape with Exactag.
Testing
- Trigger a
pageand anOrder Completedevent on your site (or via Signal’s event debugger). - In Signal’s Event Debugger, confirm the outbound request targets
m.exactag.com/s2s/pi.ashxand thatsitegroup,euk, and (for conversions)orderid/totalpriceare populated. - A
2xxresponse from Exactag indicates the impression/conversion was accepted. - Ask your Exactag contact to confirm the events are appearing against the correct sitegroup in the Exactag UI — there may be a short processing delay.
Troubleshooting
| Problem | Solution |
|---|---|
401 / 403 responses | The campaign code is wrong or not active. Re-check campaign_code with Exactag. |
| Events accepted but not visible in Exactag | The sitegroup value does not match a configured event/sitegroup for your brand. Confirm the correct codes with Exactag and update the event mappings. |
| Conversions missing revenue | Ensure your Order Completed event sends revenue (mapped to totalprice) and order_id (mapped to orderid). |
| Wrong visitor geo / device in Exactag | Confirm Signal is forwarding the original X-Forwarded-For and User-Agent headers (default behaviour). |
| Returning visitors counted as new | Check that context.session.number is populated so sescount is greater than 1 on repeat sessions. |