Recently I need to do restructuring the website for a piece of partnership project, and this work is blended with cookie and url manipulation. In this blog, I will explain about the usage of cookie in our project and how we do with it.
So first, how tasty is a cookie? I like choco flavour :) (…joking!).
We know that HTTP is a stateless protocol. But for a commercial website, we need to have session information for various purpose like:
- Session management: Logins, shopping carts, game scores, or anything else the server should remember;
- Personalisation: User preferences, themes, and other settings;
- Tracking: Recording and analysing user behaviour;
That’s where we use the cookie for. A cookie is a small file with the maximum size of 4KB that the web server stores on the client computer. It allows us to track the state of the application. Now, when the visitor arrives at another page on your site, the browser sends the same cookie to the server for retrieval. Once retrieved, your server knows/remembers what was stored earlier.
How cookies are created ?
Well. they are baked at 200 c obviously (…joking again).
In reality, these are done through following steps (between the server and browser):
- After receiving an HTTP request, a server can send one or more
Set-Cookie
headers with the response to set a cookie with a unique “session identifier”. - The cookie is usually stored by the browser.
- Then the cookie is sent with requests made to the same server inside a
Cookie
HTTP header. - An expiration date or duration can be specified, after which the cookie is no longer sent. Additional restrictions to a specific domain and path can be set, limiting where the cookie is sent.
What are the ingredients of a cookie?
Cookies are a plain text data record of 5 variable-length fields :
- Name=Value (compulsory) − Cookies are set and retrieved in the form of key-value pairs
There are following optional fields:
- Expires − The date the cookie will expire. If this is blank, the cookie will expire when the visitor quits the browser. This can be
max-age
orexpires
field.max-age=max-age-in-seconds
(e.g.,60*60*24*365
or 31536000 for a year).expires=date-in-GMTString-format
If neitherexpires
normax-age
specified it will expire at the end of session. - Domain − The domain name of your site. If not specified, this defaults to the host portion of the current document location.
- Path − The path to the directory or web page that set the cookie.
path=path
(e.g., '/
', '/mydir
') If not specified, defaults to the current path of the current document location. - Secure − If this field contains the word “secure”, then the cookie may only be retrieved with a secure server. If this field is blank, no such restriction exists.
Any of the following fields are linked together by a semi-colon separator:
document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"
How do I bake … I mean set a cookie?
Since we are in JavaScript world, luckily we can manipulate cookies using the cookie property of the Document object. JavaScript can read, create, modify, and delete the cookies that apply to the current web page.
Reading all the cookies:
document.cookie; // cookie1=value1; cookie2=value2;…
Writing a certain cookie:
A write operation to document.cookie
updates only cookies mentioned in it, but doesn’t touch other cookies.
For instance, this call sets a cookie with the name application
:
document.cookie = "application=finish"; // update only cookie named 'application'
However to ensure valid information get passed, sincename and value can have any characters, to keep the valid formatting they should be escaped using a built-in encodeURIComponent
function:
// special characters (spaces), need encoding
let name = "application";
let value = "half finish"// encodes the cookie as application=half%finish
document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value);
Also noted that the value
part of the field can be a complicated and nested json object.
There are also ways to get specific cookie, set specific cookie, and delete cookie:
Get cookie
// returns the cookie with the given name,
// or undefined if not found
function getCookie(name) {
// find anything that matches: ; name=<value>. let matches = document.cookie.match(new RegExp(
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
));
return matches ? decodeURIComponent(matches[1]) : undefined;
}//Set cookie:
function setCookie(name, value, options = {}) { options = {
path: '/',
...options
}; if (options.expires instanceof Date) {
options.expires = options.expires.toUTCString();
} let updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value); for (let optionKey in options) {
updatedCookie += "; " + optionKey;
let optionValue = options[optionKey];
if (optionValue !== true) {
updatedCookie += "=" + optionValue;
}
} document.cookie = updatedCookie;
}Delete cookiefunction deleteCookie(name) {
setCookie(name, "", {
'max-age': -1 // or expires date in the past or 0
})
}
But these seems to be tedious to remember. And there are tons of nice libraries our that to help you:
Personally, I like js-cookie
:
You can pass in name-values as object which is very user friendly in JS environment.
For example, to create an expiring cookie, valid to the path of the current page:
Cookies.set('name', 'value', { expires: 7, path: '' })
It’s powerful to use it with lodash together. For example we can merge some cookie fields:
import Cookie from “js-cookie”;
import { merge } from “lodash”;export function mergeCookieContent(
cookieName: string,
key: string,
value: any
): void {
const existingCookie = Cookie.getJSON(cookieName);
const updatedCookie = merge(existingCookie, {[key]: value});
Cookie.set(cookieName, updatedCookie, { domain: “.abc.com” });
}
Another example to update certain value field from the specific cookie :
import Cookie from "js-cookie";
import { omit } from "lodash";// Get existing journey info and remove current selection
const userJourney = Cookie.getJSON(“application”);const updatedUserJourney = omit(userJourney, purchasingPurpose);
Cookie.set(“application”, updatedUserJourney, { domain: “.abc.com” });
So the application field is
{%22details%22:{%22occupationStatus%22:%22EMPLOYED%22}%2C%22purchasingPurpose%22:%22PLAY%22%2C%22dealEnd%22:%22less_than_6_months%22}
After call getJson we have a json representative of the value field (instead of decode it ourselves):
dealEnd: “less_than_6_months”details: {occupationStatus: “EMPLOYED”}purchasingPurpose: “PLAY”
And then we delete the `purchasingPurpose` field before eset the cookie again aka updating it.
You can even mix it with url params:
import cookie from "cookie";
import querystring from "querystring";
export const getReferrerFromCookie: () => string | undefined = () => {
try {
const landingParamsCookie = cookie.parse(document.cookie)["landing-params"];
// we convert landing-params from referrer%3Dabc (raw) to
// referrer=abc
const landingParams = querystring.parse(landingParamsCookie);
// {referrer: "abc"}
return landingParams.referrer as string;
} catch (_) {
return undefined;
}
};
export const setLandingParamsCookie = () => {
// Set landing-params cookie
if (typeof window !== "undefined") {//make sure window object exist
if (window.location.search) {
// set expiry date to 30 minutes from now
const expiryDate = new Date(60 * 1000 * 30 + Date.now()).toUTCString();
const query = encodeURIComponent(
window.location.search.replace(/^\?/, "")
);
document.cookie = `landing-params=${query};domain=.abc.com;expires=${expiryDate}`;
}
}
};
So, that’s pretty much it. Hopefully you can bake your own cookie from now on.
Happy Reading!