First-Party Cookie Longevity Under Safari ITP and Firefox ETP: CNAME Cloaking Bans and Server-Side Set-Cookie

In Apple WebKit on macOS, iOS, and iPadOS, any first-party cookie written or updated through client-side JavaScript via document.cookie is automatically

Conceptual 3D timeline comparison on a charcoal surface where a thin blue client-side glass rod fractures at a red laser barrier while a reinforced emerald-and-gold server-side conduit shines across the entire frame.

In Apple WebKit on macOS, iOS, and iPadOS, any first-party cookie written or updated through client-side JavaScript via document.cookie is automatically capped at a maximum lifetime of 604,800 seconds (7 days), regardless of whether the script specifies Max-Age=31536000 or an Expires timestamp years in the future. When that same user arrives on a publisher property via a cross-site navigation containing query parameters or URL fragments, WebKit compresses the expiration ceiling down to 86,400 seconds (24 hours). For programmatic publishers, this client-side storage decay directly erodes bid density, resets frequency caps, and fragments audience cohorts across Safari and iOS traffic.

Because Apple enforces WebKit (WKWebView) across browser engines on iOS in most global markets and Mozilla Firefox enforces parallel defenses through Enhanced Tracking Protection (ETP) and Total Cookie Protection, client-side JavaScript identity wrappers cannot sustain persistent user recognition on their own. When a reader visits a news, sports, or lifestyle site once every eight days on an iPhone, every client-side identifier stored by Prebid.js 11.x User ID submodules is purged before the next session begins. To downstream demand-side platforms (DSPs) evaluating an OpenRTB 2.6 bid request, that loyal subscriber looks identical to a first-time anonymous visitor with zero behavioral history.

Engineering teams can no longer rely on client-side storage APIs or DNS CNAME workarounds to maintain first-party state. Preserving durable, privacy-compliant first-party identity requires moving cookie orchestration out of the browser runtime and onto the publisher's first-party HTTP edge infrastructure, aligning network topology with browser DNS inspection rules and emerging server-side execution frameworks.

How Apple WebKit Intelligent Tracking Prevention (ITP) Caps All Script-Writable Storage at 7 Days

Under WebKit's full third-party cookie blocking and script-writable storage policy, Safari Intelligent Tracking Prevention (ITP) blocks all third-party cookies by default, downgrades cross-site document.referrer headers to the origin, and enforces a strict 7-day cap (or 24 hours on link-decorated bounce navigations) on all script-writable storage including document.cookie, LocalStorage, IndexedDB, and Service Worker caches. This enforcement does not distinguish between a third-party tracking script injected via an external tag manager and a publisher's own first-party application bundle hosted on the primary domain. If the storage mutation originates from the JavaScript execution context rather than a verified first-party HTTP response header, WebKit classifies the state as script-writable and applies the countdown timer.

Timeline bar chart comparing Safari ITP script-writable document.cookie storage capped at 7 days and 24 hours against a first-party HTTP Set-Cookie header persisting past 90 days.

While Apple focuses on bounding the lifetime of client-side first-party storage, Mozilla Firefox ETP complements third-party cookie blocking with Total Cookie Protection (dynamic state partitioning) and Periodic Cookie Purging. Firefox isolates all cookies, LocalStorage, and cache objects into separate storage jars keyed by the top-level eTLD+1 domain, preventing any cross-site script from correlating identifiers across two different publisher properties. In tandem, these browser policies mean that programmatic stacks must be engineered around identity-resilient monetization architectures that treat browser-writable storage as volatile session cache rather than permanent identity storage.

Why LocalStorage, IndexedDB, and document.cookie Expire After 7 Days Without User Interaction

When WebKit initially restricted document.cookie lifetimes in earlier iterations of ITP, many ad tech vendors and User ID providers migrated their persistence layers in Prebid.js from cookies (storage.type: "cookie") to HTML5 window.localStorage (storage.type: "html5") or IndexedDB. Because LocalStorage does not natively support an Expires or Max-Age attribute in the W3C Web Storage specification, developers assumed entries written there would persist indefinitely until cleared by the user. WebKit closed this loophole completely by binding the 7-day expiration policy to the underlying NetworkStorageSession and origin-level storage quota manager rather than just the cookie jar.

In modern Safari, if a user visits publisher.com, loads a page where Prebid.js writes encrypted extended identifiers (eids) to LocalStorage and document.cookie, and then closes the tab, a 7-day inactivity timer starts for all script-writable data associated with that origin. If the user returns to publisher.com and performs a direct interaction (such as a tap, click, or form submission) on day 5, WebKit resets the 7-day clock. However, if the user returns on day 8, the browser's background maintenance task has already evicted the LocalStorage keys, wiped the IndexedDB object stores, cleared Service Worker caches, and deleted every script-set cookie.

For programmatic yield management, this 7-day cliff creates a measurable revenue drop on returning weekly cohorts. When Prebid.js initializes on day 8 without persisted storage, User ID submodules must either fire asynchronous external sync requests (increasing auction latency and missing the initial header bidding timeout window) or generate a brand-new anonymous UUID. Without continuity in the user.ext.eids array of the OpenRTB 2.6 bid request, tier-1 DSPs cannot match the impression to an existing audience segment or verify cross-session frequency caps. Consequently, DSP bid shading algorithms price the impression at the unauthenticated baseline floor, compressing clearing prices by 35% to 55% compared to matched Safari sessions.

The storage retention problem becomes even more acute for publishers that acquire significant audience volume from social platforms, search engines, content aggregators, or email newsletters. WebKit's on-device classifier continuously monitors cross-site navigations to identify domains that have the ability to track users across sites. When a user clicks a link on a classified source domain (for example, a social feed or search engine results page) and lands on publisher.com/?utm_source=social&click_id=98765, WebKit inspects the destination URL for query parameters (?) or fragment identifiers (#).

If the destination URL is decorated with query strings or fragments and the referring domain is classified by ITP as having cross-site tracking capabilities, WebKit designates the session as a link-decorated cross-site navigation. Under this designation, all script-writable storage (document.cookie, LocalStorage, IndexedDB, and Cache API) created or modified during that page load is restricted to a 24-hour time-to-live (TTL). This prevents bounce trackers and click-ID decorators from using first-party JavaScript storage to bridge cross-site identity over a multi-day window.

For AdOps teams managing paid audience acquisition or newsletter recirculation, the 24-hour cap creates immediate attribution and monetization friction. A reader who clicks a morning newsletter link with UTM parameters on an iPad and returns the following afternoon via a bookmark will find their client-side consent preferences, frequency cap counters, and Prebid User IDs completely erased if the user did not trigger an un-decorated navigation in between. Stripping query parameters via window.history.replaceState() after page load does not bypass this restriction, because WebKit evaluates the navigation URL at the network response phase before JavaScript executes on the main thread.

Why CNAME Cloaking Is Blocked by Safari and Firefox DNS Inspections

Because WebKit's 7-day and 24-hour caps apply specifically to storage mutated via client-side scripts (document.cookie), the browser still permits cookies set via standard HTTP Set-Cookie response headers from the publisher's first-party server to persist Beyond 7 days. Recognizing this distinction, several third-party analytics and identity vendors historically instructed publishers to configure DNS CNAME (Canonical Name) records. Under a CNAME cloaking setup, a publisher would delegate a subdomain such as id-sync.publisher.com to resolve via DNS CNAME to collector.thirdparty-vendor.com.

When the browser requested a script or pixel from https://id-sync.publisher.com/sync, the request appeared at the HTTP layer to be same-site (publisher.com), allowing the third-party vendor's origin server to read all non-scoped first-party cookies on publisher.com and return an HTTP Set-Cookie header with a multi-year expiration. Both Apple WebKit and Mozilla Firefox quickly engineered network-layer countermeasures to neutralize CNAME cloaking and protect user privacy:

  1. WebKit DNS and IP Subnet Verification: Starting in Safari 14 and iOS 14, WebKit resolves the full DNS CNAME chain for every subresource request and compares the resolved IP address of the subdomain against the resolved IP address of the main document (publisher.com). If a first-party subdomain resolves through a CNAME record to a third-party domain (a different eTLD+1) and the resulting IP address does not share the same /24 IPv4 subnet (or /48 IPv6 prefix) as the top-level document's host, WebKit flags the connection as a third-party CNAME-cloaked endpoint. Any Set-Cookie header returned by that endpoint is automatically capped at a 7-day expiry, matching the restriction placed on document.cookie.
  2. Firefox ETP CNAME Uncloaking via DNS-over-HTTPS (DoH): Mozilla Firefox integrates native DNS CNAME inspection directly into its network stack (nsIDNSService). When Firefox resolves a first-party subdomain, it inspects every intermediate and final CNAME record in the resolution chain against its Enhanced Tracking Protection blocklists. If the canonical target matches a known third-party tracking or cross-site ad tech domain, Firefox blocks the network request entirely or strips the Cookie and Set-Cookie headers before they reach the remote server.

Beyond the technical failure of CNAME cloaking in Safari and Firefox, delegating a first-party subdomain via CNAME to an external vendor creates severe security liabilities. If a publisher sets cookies at the root domain (.publisher.com) without strict host-only scoping, a CNAME-cloaked third-party server automatically receives every cookie transmitted by the browser, including session authentication tokens, paywall credentials, and subscriber PII. Modern publisher solutions reject CNAME delegation entirely, replacing DNS workarounds with true first-party edge termination.

Setting First-Party Secure HttpOnly Cookies and Exploring IAB Tech Lab Trusted Server

To achieve durable first-party cookie persistence across Safari and Firefox without triggering CNAME penalties, the HTTP Set-Cookie header must be issued by an origin server or CDN edge worker that shares the exact IP network boundary and TLS authority of the primary document host. When the publisher's own CDN edge (such as a Cloudflare Worker, AWS CloudFront Function, or Fastly Compute service terminating traffic for www.publisher.com) sets a cookie directly on the HTML document response or a same-origin first-party API route (https://www.publisher.com/api/v1/session), WebKit recognizes the cookie as an authentic server-side first-party cookie.

However, AdOps engineers must navigate two critical WebKit rules when configuring server-side Set-Cookie headers:

  • JavaScript Overwrite Downgrade: If a server sets a first-party cookie via HTTP Set-Cookie with a 180-day Max-Age, and a client-side script on the page subsequently overwrites or updates that exact cookie name using document.cookie, WebKit permanently downgrades that cookie's classification to script-writable and enforces the 7-day (or 24-hour) expiration cap.
  • The Dual-Token Architecture (HttpOnly Anchor + Hydration): By setting the primary first-party identity token with the HttpOnly, Secure, and SameSite=Lax flags, the publisher guarantees that no client-side JavaScript on the page can accidentally mutate or overwrite the cookie, preserving its full server-defined TTL (up to WebKit's 400-day standard HTTP cookie upper bound). Because Prebid.js cannot read an HttpOnly cookie via document.cookie, the edge server reads the incoming HttpOnly cookie on page request and either injects the decrypted eids payload directly into the HTML document's pbjs.setConfig({ ortb2 }) object or mints a separate, read-only companion cookie that Prebid.js reads without modifying.

The following edge middleware implementation demonstrates how a publisher's first-party server or CDN worker maintains a durable HttpOnly primary identifier while hydrating a readable Prebid state on every page request:

// First-Party Edge Middleware (e.g., Cloudflare Worker on www.publisher.com)
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    const cookieHeader = request.headers.get("Cookie") || "";
    const cookies = Object.fromEntries(
      cookieHeader.split(";").map(c => {
        const [k, ...v] = c.trim().split("=");
        return [k, v.join("=")];
      }).filter(([k]) => k)
    );

    // 1. Read authoritative HttpOnly first-party ID or generate a new UUIDv4
    let fpId = cookies["__Host-sb_fpid"];
    if (!fpId || !/^[0-9a-f-]{36}$/i.test(fpId)) {
      fpId = crypto.randomUUID();
    }

    const response = await fetch(request);
    const newHeaders = new Headers(response.headers);

    // 2. Refresh the authoritative HttpOnly cookie (180-day TTL, immune to JS overwrite)
    const maxAge = 180 * 24 * 60 * 60; // 15,552,000 seconds
    newHeaders.append(
      "Set-Cookie",
      `__Host-sb_fpid=${fpId}; Max-Age=${maxAge}; Path=/; Secure; HttpOnly; SameSite=Lax`
    );

    // 3. Emit a companion readable cookie for Prebid.js (never written by document.cookie)
    newHeaders.append(
      "Set-Cookie",
      `sb_pbjs_id=${fpId}; Max-Age=${maxAge}; Path=/; Secure; SameSite=Lax`
    );

    return new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: newHeaders
    });
  }
};

On the client side, Prebid.js 11.x is configured to read the edge-minted identifier and pass it into the OpenRTB 2.6 first-party data and extended ID (user.ext.eids) structures without ever calling document.cookie = ... on that cookie name:

window.pbjs = window.pbjs || { que: [] };

function getEdgeCookie(name) {
  const match = document.cookie.match(new RegExp("(^| )" + name + "=([^;]+)"));
  return match ? decodeURIComponent(match[2]) : null;
}

pbjs.que.push(function() {
  const edgeFirstPartyId = getEdgeCookie("sb_pbjs_id");

  if (edgeFirstPartyId) {
    pbjs.mergeConfig({
      ortb2: {
        user: {
          id: edgeFirstPartyId,
          ext: {
            eids: [
              {
                source: "publisher.com",
                uids: [
                  {
                    id: edgeFirstPartyId,
                    atype: 1,
                    ext: { stype: "ppid" }
                  }
                ]
              }
            ]
          }
        }
      }
    });
  }
});

This architectural shift toward first-party edge execution aligns directly with emerging IAB Tech Lab standards. Specifically, the IAB Tech Lab's Trusted Server initiative shifts ad auction and identity orchestration from third-party browser scripts to a publisher-controlled first-party edge cloud infrastructure to preserve first-party signals and prevent data leakage. Under the Trusted Server framework, when a browser requests a page from the publisher's origin, the publisher's edge environment validates consent strings (GPP / TCF 2.2), reads first-party HttpOnly identity cookies, executes server-side OpenRTB 2.6 requests via Prebid Server, and returns the winning ad markup or signals without exposing user headers or raw IP addresses to dozens of unverified client-side JavaScript tags.

When publishers combine edge-persisted first-party cookies with a hybrid mediation stack that balances client-side signals and Prebid Server orchestration, they eliminate the 7-day Safari identity decay while reducing browser main-thread CPU contention. For AdOps and platform engineering teams auditing their monetization stack against Safari ITP and Firefox ETP, the operational mandate is clear:

  1. Audit and Remove CNAME Aliases: Decommission all third-party DNS CNAME records used for identity or analytics collection; route all first-party traffic through the primary CDN edge sharing the document's IP subnet.
  2. Isolate Server Cookies from Client Mutations: Issue an authoritative __Host- prefixed HttpOnly; Secure; SameSite=Lax cookie from the first-party HTTP edge and strictly forbid client-side scripts from writing to that cookie name via document.cookie.
  3. Hydrate OpenRTB 2.6 user.ext.eids and Google PPID Server-Side: Inject the verified first-party identifier directly into ortb2.user.ext.eids and Google Ad Manager's setPublisherProvidedId() on page initialization so every auction starts with durable, zero-latency identity state.
Next step

Put it to work.

Every pattern in this article runs on our unified SSP and monetization platform: GAM and MCM management, Prebid client and server-side, and CTV SSAI.

Net-30 / Net-60 terms · 100% brand-safe demand