Cookies
Objectives
By the end of this chapter, you should be able to:
- Read and write a cookie with
document.cookie - Delete a cookie by setting its expiration in the past
- Explain when a cookie is a better fit than
localStorage
๐ก Why this matters: Cookies predate
localStorageby two decades, and they still do one thinglocalStoragecan’t: get automatically sent to the server with every request. That makes them the right tool for a specific, common job, even in a modern project.
What You’re Building
A cookie consent banner, the kind almost every site shows a first-time visitor, plus a dark mode toggle that remembers its setting the same way.
cookie-demo/
โโโ index.html
โโโ script.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cookie Preferences Demo</title>
</head>
<body>
<h1>Welcome</h1>
<div id="consentBanner">
<p>We use cookies to remember your preferences.</p>
<button id="acceptBtn">Accept</button>
</div>
<button id="darkModeBtn">Toggle Dark Mode</button>
<script src="script.js"></script>
</body>
</html>
Everything from here on goes in script.js.
Step 1: Check for Existing Consent on Load
document.cookie reads every cookie as one semicolon-separated string, so reading a specific one takes a small amount of parsing first.
function getCookies() {
return Object.fromEntries(
document.cookie.split("; ").filter(Boolean).map((pair) => pair.split("="))
);
}
const banner = document.getElementById("consentBanner");
function checkConsent() {
const cookies = getCookies();
if (cookies.consent === "true") {
banner.style.display = "none";
return true;
}
banner.style.display = "block";
return false;
}
checkConsent();
On a first visit, there’s no consent cookie yet, cookies.consent is undefined, and the banner shows. .split("; ") breaks the raw cookie string into "name=value" pairs, .map((pair) => pair.split("=")) breaks each of those into a [name, value] array, and Object.fromEntries() (Course 1) turns the whole list into a plain object you can check properties on.
Step 2: Set a Cookie When the User Accepts
const acceptBtn = document.getElementById("acceptBtn");
acceptBtn.addEventListener("click", () => {
document.cookie = "consent=true; expires=Fri, 31 Dec 2027 00:00:00 UTC; path=/";
banner.style.display = "none";
});
Clicking “Accept” writes a consent cookie, expires set a couple of years out, and hides the banner immediately, no reload required. path=/ makes the cookie available on every page of the site, not just whichever page set it, the most common value for path.
Step 3: Add a Second Cookie Alongside It
Writing a new cookie never erases the others, document.cookie = "..." adds or updates one cookie at a time.
const darkModeBtn = document.getElementById("darkModeBtn");
darkModeBtn.addEventListener("click", () => {
const cookies = getCookies();
const isDark = cookies.theme === "dark";
document.cookie = `theme=${isDark ? "light" : "dark"}; path=/`;
});
Clicking “Toggle Dark Mode” now sets a second, independent cookie, theme, right alongside consent. After accepting cookies and toggling dark mode once, document.cookie holds both: "consent=true; theme=dark".
Step 4: Let the User Revoke Consent
There’s no dedicated delete method for a cookie, deleting one means overwriting it with an already-expired date.
function revokeConsent() {
document.cookie = "consent=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/";
banner.style.display = "block";
}
Calling revokeConsent() removes the consent cookie (the browser drops any cookie whose expiration has passed) and brings the banner back, exactly as if this were a first visit again. Notice theme is untouched, revokeConsent() only rewrites the consent cookie, nothing else.
Cookies vs. localStorage
This banner could have been built with localStorage instead, so why cookies? A cookie is automatically included in every HTTP request to its site, which matters the moment a server needs to know about it too, session identifiers, authentication tokens, anything the backend has to see on every request. localStorage is never sent to the server at all, it only exists for the page’s own JavaScript. A consent banner is genuinely a case where either works, this lesson used cookies because it’s the classic example, but a login session token is a case where only a cookie will do.
The Complete script.js
function getCookies() {
return Object.fromEntries(
document.cookie.split("; ").filter(Boolean).map((pair) => pair.split("="))
);
}
const banner = document.getElementById("consentBanner");
const acceptBtn = document.getElementById("acceptBtn");
const darkModeBtn = document.getElementById("darkModeBtn");
function checkConsent() {
const cookies = getCookies();
if (cookies.consent === "true") {
banner.style.display = "none";
return true;
}
banner.style.display = "block";
return false;
}
checkConsent();
acceptBtn.addEventListener("click", () => {
document.cookie = "consent=true; expires=Fri, 31 Dec 2027 00:00:00 UTC; path=/";
banner.style.display = "none";
});
darkModeBtn.addEventListener("click", () => {
const cookies = getCookies();
const isDark = cookies.theme === "dark";
document.cookie = `theme=${isDark ? "light" : "dark"}; path=/`;
});
Try It
Extend the consent banner from this lesson:
- Add a
"declined"state: a “Decline” button that setsconsent=false(instead oftrue) and still hides the banner, without ever showing the dark mode toggle’s effect (skip actually applying a theme, just track the cookie). - Change
checkConsent()so it also reads thethemecookie on load and logs`Theme preference: ${cookies.theme}`if one exists. - Add a “Reset everything” button that deletes both the
consentandthemecookies in one click, and confirmdocument.cookieis empty afterward.
Recap
document.cookiereads every cookie as one string, writing to it adds or updates a single cookie without clearing the rest, this lesson’s accept and dark-mode buttons each set their own cookie independently.expirescontrols when a cookie is removed automatically,path=/makes it available across the whole site.- There’s no delete method, setting a cookie with a past
expiresremoves it, exactly whatrevokeConsent()did. - Cookies are sent with every request to the server,
localStoragenever is, that’s the deciding factor between them.
Next lesson: the Geolocation API, asking the browser for the user’s physical location.