The latest version of Apple’s Safari includes an enhancement to Webkit's ITP (Intelligent Tracking Prevention) policy, published on March 24th, 2020. The new ITP policy forces a 7-day expiration for all script-writable storage. To allow the continuous valid functionality of Dynamic Yield for users visiting your site via Safari, an implementation adjustment is required on your side as described below.
About the ITP Policy Issue
To keep track of users visiting your website, the Dynamic Yield script generates and manages a unique ID for each user visiting your website. This script relies on localStorage and cookies for storing this value on the user's browser. The cookie is referred to as DYID and is saved with the key _dyid.
Apple’s ITP 2.3 released in September 2019, forces an expiration of 7 days to third-party cookies and localStorage. This includes the DYID cookie.
In case a returning Safari user does not visit your website for 7 days or more, the DYID value stored in the browser will expire from both localStorage and the cookie. This will prevent Dynamic Yield from accessing this value and therefore will view the user as if they are visiting your website for the first time. This may have many implications including historic behavioral data, audience membership data, and affinity data becoming unreachable to Dynamic Yield, resulting in targeting limitations.
What You Need To Do
To overcome this ITP limitation, the DYID cookie should be set by the backend application serving your website on your domain. Cookies set this way are considered first-party cookies, are therefore not affected by ITP, and can have a longer expiration.
Note: This solution is not designed for customers who implemented Dynamic Yield using Shopify. Speak to your Customer Success Manager to learn about a manual workaround.
- When a user visits your site, a request is sent from the browser to the backend application serving your site. For returning users, the request includes the _dyid cookie (together with all other first-party cookies).
- When receiving this request, within your backend application, duplicate the _dyid cookie value into a new cookie. Use the key _dyid_server and return the new cookie as a response header for this request, setting a 1-year expiration date. This will set the _dyid_server cookie as a server-side first-party cookie in the user’s browser which, as recommended by the ITP policy, is not affected by the cookie expiration enforcement.
- Our script will use the _dyid_server cookie as it runs on your page and as a result, no returning-user data will be lost, even if the user has not visited your site for over 7 days.
The following diagram and explanation demonstrate the flow:
- A visitor enters your website.
- Your server gets a request to return a web page from the browser. Requests from returning users include the _dyid cookie.
- Your application server does the following steps:
- Checks if the _dyid cookie was sent in this request.
- If it is, it should duplicate it to a new _dyid_server cookie.
- Set it as a response header, with a 1-year expiration date. This will set it as a server-side first-party cookie in the visitor’s browser (the _dyid cookie will also be returned, this should not change).
- Your website visitor sees the rendered content of your website.
How to Duplicate the Cookie
Let’s assume the value of the _dyid cookie is 7237284912004766755. You would duplicate the cookie value into the new _dyid_server, and set the expiration to 1 year by setting 31556951 as the max-age attribute value.
The result would be the following cookie: _dyid_server=7237284912004766755;max-age=31556951
Code Examples
As a reference, we’ve added a few code snippets for commonly used platforms and programming languages for implementing this solution.
>>> curl -v http://yoursite.example.com --cookie "_dyid=-3233584359067736988" 19:55:13
* Trying 172.217.18.4...
* TCP_NODELAY set
* Connected to yoursite.example.com (172.217.18.4) port 80 (#0)
> GET / HTTP/1.1
> Host: yoursite.example.com
> User-Agent: curl/7.64.1
> Accept: */*
> Cookie: _dyid=-3233584359067736988
>
< HTTP/1.1 200 OK
< Date: Mon, 30 Mar 2020 16:55:16 GMT
...
< Content-Type: text/html; charset=ISO-8859-1
...
< Set-Cookie: _dyid_server=-3233584359067736988; expires=Wed, 29-Apr-2021 16:55:16 GMT; path=/; domain=.google.com; Secure
// need cookieParser middleware before we can do anything with cookies
app.use(express.cookieParser());
app.use((req, res, next) => {
if (req.cookies._dyid) { // if this is a returning user and the DYID cookie exists
const dyid = req.cookies._dyid;
res.cookie('_dyid_server', dyid, { // store a new server-side cookie named "_dyid_server" with the DYID value
expires: new Date(Date.now() + 31540000000000), // Set a 1 year expiration for the new cookie
});
}
next();
});
...
dyid_cookie = request.COOKIES.get('_dyid')
if dyid_cookie is not None: # if this is a returning user and the DYID cookie exists
set_cookie(‘_dyid_server’, dyid_cookie, 31540000000000) # Store a new server-side cookie named "_dyid_server" with the DYID value
...
<?php
if(isset($_COOKIE['_dyid'])) {
$dyid_cookie = $_COOKIE['_dyid']; /* if this is a returning user and the DYID cookie exists */
setcookie('_dyid_server', $dyid_cookie, time() + 31540000000000); /* expire in 1 year */
}
...
Validating the Implementation
This procedure checks that a server-side cookie called _dyid_server is created with the same value as the _dyid cookie, but with a one-year expiration date. It can be done on any browser, but we used Chrome in this example:
- Open a new browser and navigate to any page in your website that has the Dynamic Yield script.
- Open Chrome's developer tools (Ctrl + Shift + I).
- Go to the Network tab, click the Preserve Log checkbox and click Clear.
- Refresh the page, select the first request with the URL of your site, and look at the headers.
- Verify that the value of the _dyid_server cookie is the same as the dyid value. You already have the value of the _dyid_server cookie. You can find the value of the dyid in the request headers under "cookie:". If the values match, your solution is verified.
Note: This validation can NOT be done in the Application Tab > Storage > Cookies area because this area includes both server-side and client-side cookies, so some of these will be automatically deleted by Safari.
Limitation
- Campaign targeting conditions that are based on cookies affected by this update may not function as expected. This includes the New User (first session), cookie, and elapsed time conditions.
- When users browse your site using iPADs running iOS 13 or higher, they are tracked as if they are browsing from a desktop.
- If you're enabled the Active Cookie Consent mode, it is important to wait for the consent object and act upon its result - otherwise, you might write cookies for opt-out users.