Can't set Cookie with JavaScript in Safari or iOS

Viewed 1812

I'm working on some cookie consent and terms etc.. So I made a JS function to set a cookie after user clicks "Agree" button:

...html

<button onclick="setCookie('law_cookie', 'agree_all', 90)">


...js

function setCookie(name, value, daysToLive) {
    // Encode value in order to escape semicolons, commas, and whitespace
    let cookie = name + "=" + encodeURIComponent(value);

    if (typeof daysToLive === "number") {
        /* Sets the max-age attribute so that the cookie expires
        after the specified number of days */
        cookie += ";max-age=" + (daysToLive * 24 * 60 * 60) + ';Secure;path=/';

        document.cookie = cookie;
        cookie_set = true

    }
}

Now I tested in chrom and firefox, everything works great! BUT, safari isn't able to set a cookie. I tried to initialise by clicking on the button but after reload safari hasn't set the cookie.

I checked if javascript was enabled (it was) and I also tried to set cookie = encodeURIComponent(cookie); but nothing works.

Someone has an idea what I'm doing wrong?

3 Answers

Have you tried using a private tab on safari? It may be possible that it didn’t load your new files. On my website I use the same method to write cookies and it works on Safari.

Encoding the value is good

let cookie = name + "=" + encodeURIComponent(value);

But encoding the whole sting not:

cookie = encodeURIComponent(cookie);

I modified your script I removed the 'secure' entry as that will limit it to working only with HTTPS, when you are troubleshooting give it the best chances, and add security only when everything works. In the past the might have worked with some browsers:

https://developer.mozilla.org/en-US/docs/web/api/document/cookie

;secure Cookie to only be transmitted over secure protocol as https. Before Chrome 52, this flag could appear with cookies from http domains.

And I added window.alert so you will see 3 things:

  • Proof that your button/event actually hit
  • Check that you provided the age argument (without age your condition will not save cookie)
  • Will show you what values are going to save so you can confirm if it's ok.

The modified JS:

function setCookie(name, value, daysToLive) {
    // Encode value in order to escape semicolons, commas, and whitespace
    let cookie = name + "=" + encodeURIComponent(value);

    if (typeof daysToLive === "number") {
        /* Sets the max-age attribute so that the cookie expires
        after the specified number of days */
        cookie += ";max-age=" + (daysToLive * 24 * 60 * 60) + ';path=/';

                window.alert(cookie);
        document.cookie = cookie;
        cookie_set = true
    }
}

setCookie('law_cookie', 'agree_all', 90)

Often using a lot of console.log helps with troubleshooting as well

Do you use some other frameworks which could interfere with this? Something might be doing stuff with cookies behind your back. Did you try saving cookies from the HTTP header as well?

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie

Did you try to minimalize the replicator, make smallest project which can still replicate the problem? Or start with a small self-contained JS fiddle:

https://jsfiddle.net/ao9p7e4j/1/

Here I added a function to show cookies to see what you have

Safari version 15.2, unlike Chrome and Firefox, refuses to set Secure cookies on the localhost origin, so you'll need to add a workaround just for Safari.

Related