First Party ID Cookie
Let’s begin with a straightforward step: adding the FPID (First-Party Identifier) Cookie. Why add the FPID and what are the benefits of using it?
FPID addresses the challenges posed by browsers like Safari, which use Intelligent Tracking Prevention (ITP) to limit third-party cookies and cross-site tracking. With FPID, websites can maintain user identification even when third-party cookies are blocked or deleted, as often happens under ITP’s 7-day expiration policy.
So that means that implementing FPID ensures that your anonymous visitors, along with all collected and stitched data, will be recognized as the same visitor even if they return after a week or more on certain browsers like Safari.
First-party device IDs (FPIDs) track visitors by using first-party cookies. First-party cookies are most effective when they are set using a server that uses a DNS A record (for IPv4) or AAAA record (for IPv6), as opposed to a DNS CNAME or JavaScript code.
For more information on implementing FPID with Adobe WebSDK, visit Adobe Experience League's documentation.
Implementing First Party ID for Edge Delivery Services
What options do we have for implementation?
One approach is using “Classic” AEM Sites to generate an FPID Cookie in a Servlet, as described in this guide.
But since we are anyway using Workers let’s implement the FPID generation there, directly on the edge.
Note that Adobe’s Edge Network only accepts IDs formatted according to the UUIDv4 standard.
We just extended our worker code, added a uuid library and generated a new FPID Cookie if it doesn’t exist.
You can find full code here
const cookieHeader = request.headers.get('Cookie');
let fpidValue;
if (!cookieHeader || !cookieHeader.includes(`${fpidCookieName}=`)) {
// If fpid cookie is not present, generate a new one
const { v4: uuidv4 } = require('uuid');
fpidValue = uuidv4();
} else {
// Extract the current fpid from the cookie
const cookies = cookieHeader.split(';').map(cookie => cookie.trim());
const fpidCookie = cookies.find(cookie => cookie.startsWith(`${fpidCookieName}=`));
fpidValue = fpidCookie.split('=')[1];
}
// Set or extend the fpid cookie
const expirationDate = new Date();
expirationDate.setFullYear(expirationDate.getFullYear() + 1);
const expires = expirationDate.toUTCString();
response = new Response(response.body, response);
response.headers.append('Set-Cookie', `${fpidCookieName}=${fpidValue}; Expires=${expires}; Path=/; HttpOnly; Secure`);
That same FPID Cookie name needs to be configured in Data Stream configuration
To verify that everything is functioning correctly, let's check the cookies after consent has been granted and the WebSDK call has been executed:
- fpid: This is the cookie generated by the worker. You can use any name, just ensure that the same name is Configured in the Data Stream.
- kndctr*: These are identity cookies set by the Adobe Experience Platform Web SDK Edge (ECID).
To confirm that everything is properly connected: after deleting all cookies except for the fpid (simulating Safari's behavior after a certain period), refresh the page. You should see the same ECID cookies reappear as Adobe will generate ECID based on your provided First Party ID.
Other approaches for implementation
The approach above shows implementing FPID when you have a “Bring your own CDN” setup where you can use Cloudflare workers. Similar approach can be used with different CDN providers like Akamai.