Anonymous ID
The anonymous ID is the foundation of Signal’s identity system. Every visitor to your site receives a persistent, server-generated identifier stored in the _dfid first-party cookie. This ID serves as the primary key for all identity lookups, vendor ID associations, and cross-session stitching.
The _dfid Cookie
| Attribute | Value |
|---|---|
| Name | _dfid |
| Format | UUID v4 (e.g. f47ac10b-58cc-4372-a567-0d02b2c3d479) |
| Set by | Set-Cookie response header from Ingestion Gateway |
| Domain | Customer’s subdomain (e.g. .example.com) |
| Path | / |
| httpOnly | true |
| Secure | true |
| SameSite | Lax |
| TTL | 2 years |
Why Server-Set Matters
The _dfid cookie is set via the HTTP Set-Cookie response header — not by JavaScript. This distinction is critical for Safari users.
Safari’s Intelligent Tracking Prevention (ITP) caps the lifetime of cookies set by JavaScript (document.cookie) to 7 days. In some cases, ITP reduces this further to 24 hours if the referring domain is classified as a tracker. Cookies set via Set-Cookie headers from a first-party server are exempt from these restrictions and persist for their full configured TTL.
Because the Ingestion Gateway runs on the customer’s own subdomain (e.g. data.example.com), the _dfid cookie is a genuine first-party cookie set by the first-party server. It persists for the full 2-year TTL across all browsers, including Safari.
JavaScript-set cookie: document.cookie = "_dfid=abc; max-age=63072000"
→ Safari ITP caps this at 7 days (or 24 hours)
Server-set cookie: Set-Cookie: _dfid=abc; Max-Age=63072000; HttpOnly; Secure; SameSite=Lax
→ Full 2-year lifetime in all browsersThis is the same reason Signal sets all vendor cookies (_ga, _fbp, _ttp, etc.) via server-side Set-Cookie headers rather than injecting them with JavaScript. Every cookie Signal manages benefits from ITP exemption.
First Request Flow
When a new visitor arrives on your site for the first time, the following sequence occurs:
1. Browser sends request to your site
2. Datafly.js fires a page event to the Ingestion Gateway
3. Gateway checks for _dfid cookie in the request headers
4. No _dfid found → Gateway generates a new UUID v4
5. Gateway responds with:
- Set-Cookie: _dfid={new-uuid}; Max-Age=63072000; HttpOnly; Secure; SameSite=Lax; Path=/
- JSON response body: { "success": true }
6. Browser stores the _dfid cookie automaticallyThe UUID v4 is generated using a cryptographically secure random number generator (crypto/rand in Go). There is no sequential or predictable component.
Subsequent Request Flow
On every subsequent page load or event, the browser automatically includes the _dfid cookie in requests to the Ingestion Gateway (because it is a first-party cookie on the same domain):
1. Browser sends event to Ingestion Gateway
Cookie: _dfid=f47ac10b-58cc-4372-a567-0d02b2c3d479
2. Gateway reads _dfid from the Cookie header
3. Gateway refreshes the cookie TTL by re-sending the Set-Cookie header
4. Gateway uses the _dfid as the anonymous_id in the event payload
5. Event is published to Kafka with anonymous_id attachedThe gateway refreshes the cookie TTL on every request, so active visitors never lose their identity due to cookie expiration. The 2-year TTL effectively means “2 years since last visit.”
Identity Lookup Key
The _dfid value is used as the primary key in Redis for all identity-related data:
Redis key: identity:{anonymous_id}
Example: identity:f47ac10b-58cc-4372-a567-0d02b2c3d479This Redis hash stores all associated vendor IDs, click IDs, and enrichment results for the visitor. When the Event Processor prepares an event for delivery, it looks up this hash to retrieve the vendor-specific IDs needed for each integration.
HGETALL identity:f47ac10b-58cc-4372-a567-0d02b2c3d479
→ ga_client_id "1234567890.1708876543"
→ fbp "fb.1.1708876543000.9876543210"
→ fbc "fb.1.1708876543000.IwAR3x..."
→ ttp "a1b2c3d4e5f6g7h8i9j0k1l2m3n"
→ gclid "CjwKCAjw..."
→ user_id "user_98765"The _dfid cookie is httpOnly, which means client-side JavaScript cannot read its value via document.cookie. This is intentional — it prevents XSS attacks from exfiltrating anonymous IDs. Datafly.js does not need to read the cookie directly; the browser sends it automatically with every request to the Ingestion Gateway.
Linking to Known Users
When a visitor authenticates and your application calls datafly.identify('user_98765', { ... }), the Ingestion Gateway stores the mapping between the anonymous ID and the known user ID:
HSET identity:f47ac10b-58cc-4372-a567-0d02b2c3d479 user_id "user_98765"This allows all historical events collected under the anonymous ID to be associated with the known user. Delivery Workers include both the anonymous ID and the user ID in outbound payloads when the vendor API supports it.
Cookie Scope and Subdomains
The _dfid cookie is set on the customer’s root domain (e.g. .example.com), which means it is shared across all subdomains:
www.example.com— main siteshop.example.com— e-commerce storefrontblog.example.com— content site
All subdomains share the same _dfid value as long as they send events to the same Ingestion Gateway endpoint. For cross-domain identity (e.g. example.com to different-brand.com), see Cross-Domain Identity.