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.
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.
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.
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`;
}
}
}