Skip to content

Instantly share code, notes, and snippets.

@dphiffer
Last active March 28, 2020 17:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dphiffer/b7081c02bbfdfd072ae5dccf1c309d8f to your computer and use it in GitHub Desktop.
Save dphiffer/b7081c02bbfdfd072ae5dccf1c309d8f to your computer and use it in GitHub Desktop.

OMG cookies 😱

On March 6, 2020 Jerome Paulos tweeted a screenshot to @themarkup informing us that our website had a cookie on it. This is bad because we've tried hard avoid using any tracking, and as of today themarkup.org does not serve any cookies.

Where'd the cookie come from?

As my colleague Simon Fondrie-Teitler responded:

Oh, thanks for catching this! I'm guessing those are Stripe-related cookies. If you go to the donate page, enter a number, and click "donate" the stripe javascript does load a couple cookies. See https://themarkup.org/donations/ for more info.

In my testing I found that if I loaded the Stripe API JavaScript onto the page it would reliably set two cookies:

  • __stripe_sid=(uuid)
  • __stripe_mid=(uuid)

I don't know for sure what these cookies are used for and I'm okay with leaving it a mystery. We're a little unusual in our approach to cookies and tracking, so I don't blame Stripe for assuming we wouldn't care.

Delayed cookies

One thing that we already did get right with the Stripe API is intentionally delay loading their JavaScript libary onto the page until a user actually clicks on the donate button. That is, you have to visit the donate page, and then once you click on the pink button that says Donate to the Markup we dynamically load up the Stripe JavaScript needed to process the donation.

Here's what the code looks like:

  /**
   * Handle the loading of external dependencies. If Stripe is already defined, then we're already
   * good to go.
   *
   * @return Promise
   */
  function loadStripe() {
    if (typeof Stripe === 'function') {
      return Promise.resolve();
    }

    return new Promise(resolve => {
      const script = document.createElement('script');
      script.src = 'https://js.stripe.com/v3/';
      script.onload = () => resolve();
      document.head.appendChild(script);
    });
  }

However, we had not accounted for what happens after the cookies are set, which is that they stick around for every subsequent visit to pages across themarkup.org.

What we did with the cookies

The very short version of how we dealt with this is: we now delete the cookies. There's a little JavaScript that loads up on each page load and checks for cookies, any cookies. If a cookie is found, we delete it. This approach is nice because if some other library inadvertantly drops a cookie without us realizing it, the code will take care of those ones too.

  function deleteCookies() {
    // We do not set cookies intentionally, but third-party services like Stripe
    // have been known to leave some around. This will make sure we clean up
    // after them.
    const cookies = document.cookie.split(';');
    const domain = window.location.hostname;

    for (let cookie of cookies) {
      let cookieMatch = cookie.match(/^\s*([^=]+)=/);
      if (cookieMatch) {
        let cookieName = cookieMatch[1];
        document.cookie = `${cookieName}=clear; path=/; domain=.${domain}; max-age=0`;
      }
    }
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment