Cookies were first invented in 1994 by a computer programmer named Lou Montulli. Without them, the web would be quite a different place. Whether your logging into the back-end of your WordPress site or closing an annoying popup window, you use and interact with cookies every day (even if you don’t realize it).
By now, you’ve probably guessed that when we refer to cookies, we mean the cookies used to store important visitor information on a website, not the yummy chocolate chip kind. 🍪
Today we’re going to dive into the sometimes confusing topic of cookies and PHP sessions. Specifically, everything you need to know about how WordPress uses them, along with some common issues that you should be aware of (especially as a developer) when it comes to hosting your website, custom code, or using a third-party plugin. In our opinion, this subject isn’t discussed enough.
What Are Cookies?
A cookie (also referred to as a web cookie, tracking cookie, HTTP cookie, browser cookie) is a small piece of data stored by a user’s browser (Chrome, Firefox, etc.) when they visit a website. It contains information regarding browsing activity and is typically used to personalize the user’s experience or for authentication and verification purposes. Session cookies and persistent cookies are common types of cookies.
- Types of Cookies
- How WordPress Core Uses Cookies
- How Third-Party WordPress Plugins and Themes Use Cookies
- Cookies and WordPress Caching
- How to See and Clear Cookies
- GDPR and Cookies
- PHP Sessions
Types of Cookies
There are two different types of cookies that are commonly set: session cookies and persistent cookies.
Session Cookies
Session cookies, also known as transient cookies, are temporary. They don’t have an expiration date attached and only store information about what the user does during a single session. A session is simply a randomly generated/unique value that is assigned when someone visits a website. Session cookies are stored temporarily in memory and are automatically removed when the browser closes or the session ends.
Suggested reading: How to Improve PHP Memory Limit in WordPress.
Persistent Cookies
Persistent cookies, as you might have guessed, are those that contain an expiration date. These last much longer and are stored on disk until they expire or are manually cleared by the user. These are also sometimes referred to as “tracking cookies,” as these are the types of cookies that Google Analytics, AdRoll, Stripe, etc. all use.
Our Kinsta affiliate program is another example. A 60-day cookie is placed in the user’s browser when they click on an affiliate link. This ensures that the referrer gets proper credit, even if the person has closed and re-opened their browser multiple times.
How WordPress Core Uses Cookies
When we refer to WordPress core, we simply mean the files that make up the open source project, before installing any third-party plugins or themes. It’s WordPress in its natural state as we like to call it.
Now that you know the basics of what a cookie is and the different types, let’s take a look at why and how WordPress core uses them to make all that magic happen behind the scenes. Fun fact: Cookie was originally derived from the term “magic cookie.”
WordPress core uses cookies for two different purposes:
1. Login Cookies
Login cookies contain authentication details and are used when a user logs into the WordPress admin dashboard. According to the WordPress Codex, a couple of different session cookies are set:
- On login, WordPress uses the
wordpress_[hash]
cookie to store authentication details (limited to the/wp-admin/
area). - After login, WordPress sets the
wordpress_logged_in_[hash]
cookie. This indicates when you’re logged in and who you are.
When you try to access the back-end of your WordPress site, a check is done to see if the two cookies above exist and haven’t expired. This is what allows you to magically bypass the wp-login.php
screen. 😉
WordPress also sets wp-settings-{time}-[UID]
cookies. The ID being your user ID from the WordPress users database table. This stores personal dashboard and admin interface settings.
2. Comment Cookies
By default, there are cookies set when someone comments on a blog post (with an expiration of 347 days). This is so if they come back later they don’t have to fill out all the information all over again. The following three cookies are stored:
comment_author_[hash]
comment_author_email_[hash]
comment_author_url_[hash]
However, with recent privacy policy changes due to GDPR, new tools have been introduced by WordPress core to make sure you let users opt-in to these cookies being set. This setting, if not already set, can be enabled under “Settings → Discussion” in your WordPress admin dashboard. Select the option to “Show comments cookies opt-in checkbox.” The popular Akismet plugin also allows you to display a privacy notice.
How Third-Party WordPress Plugins and Themes Use Cookies
Just like WordPress uses cookies for certain functionality, third-party plugins and themes you install also set cookies. Most of them use a combination of browser cookies and database rows stored in the wp_options
table or their own custom table. This is because WordPress is stateless.
A stateless app is an application program that does not save client data generated in one session for use in the next session with that client. Each session is carried out as if it was the first time and responses are not dependent upon data from a previous session. – TechTarget
With new privacy laws, it’s more important than ever to actually understand what cookies are being set and if they are providing a way for your visitors to opt-in. Tip: not all cookies require opt-in. Read our in-depth post on GDPR to get a better understand of new requirements.
Here are just a couple of the many examples of what cookies are used for:
- If you have a popup box on your WordPress site and a visitor closes it, this typically will set a cookie so that it doesn’t come back again.
- Items added to a shopping cart on your ecommerce site. A cookie is stored so that the shopping cart keeps your products while you continue to browse around the site.
- IP Geolocation features might store the IP address and latitude/longitude coordinates of the visitor browsing the site. This is typically used to show specific content to a certain region or perhaps even redirect the user to a different subsite.
- Tracking activity across clicks with a link shortener like the PrettyLinks plugin.
- Newsletter plugin might set a cookie for users if they’ve already subscribed, this gives the ability to hide the newsletter box completely.
Essentially any action or opt-in on a WordPress site, typically will involve setting a cookie in the browser behind the scenes. The goal of this is, of course, to try and help improve the browser experience or provide additional functionality through verification.
WooCommerce Cookies
Ecommerce plugins such as WooCommerce typically have their own additional cookies they set so that buyers can easily add things to their cart, store for later when they checkout, and log in and out of their account.
To keep track of cart data, WooCommerce sets the following three cookies (no personal information is stored in the cookies):
woocommerce_cart_hash
woocommerce_items_in_cart
wp_woocommerce_session_
The first two cookies contain information about the cart and simply help WooCommerce know when the cart data changes. The third cookie wp_woocommerce_session_
contains a unique code for each customer which corresponds to an entry in the custom wp_woocommerce_sessions
table in the database.
The wp_commerce_session_
data was previously stored in the wp_options
table, but was moved to its own custom table in WooCommerce 2.5 when they introduced a new session handler. This was to improve performance, scalability, and management of sessions. Otherwise, you quickly end up with a bloated wp_options table you have to clean up.
Easy Digitial Downloads Cookies
Easy Digital Downloads by default uses WP_Session, which is a combination of browser cookies and database rows stored in the wp_options
table. Below is the cookie it sets:
edd_items_in_cart
Cookies and WordPress Caching
When it comes to WordPress cache, this is where things get tricky. Caching is essentially the process of storing resources from one request and reusing those resources for subsequent requests. Basically, it reduces the amount of work required to generate a page view. While this is great for performance, it causes a problem when it comes to cookies.
Why? Because cookies are there to perform a certain action, such as keeping the shopping cart populated while you browse around a WooCommerce site. However, if a page is served from cache, neither PHP nor the database does anything, the server simply serves up a static copy of the page.
So what can you do?
1. Use JavaScript
The first option would be to use JavaScript and update content on a page dynamically. Basically, you have HTML placeholders and use JavaScript to pull in info over an API or ajax call.
An example would be loading a list of posts in the WordPress sidebar by using JavaScript to grab a list of posts over the wp-api and then render them in the sidebar. In that scenario you could update the list of posts without clearing the page from cache since the data is generated dynamically.
This isn’t ideal though, it’s always better to cache if possible in terms of performance. But if you must have some bit of content remain dynamic while the page itself can remain static (served from cache), that’s one way to do it – use JavaScript to pull down the content for that part of the page dynamically via an API/ajax call. However, unless you can hire a WordPress developer to build a custom JavaScript solution or extension of a plugin, this option usually isn’t practical.
2. Use Admin-Ajax Calls
Admin-ajax.php
is not able to be cached, therefore you could use admin-ajax calls. A good example of this is the No Cache AJAX Widgets plugin. It makes admin-ajax calls and therefore doesn’t have to worry about conflicting with server-level or third-party caching solutions.
However, just like with JavaScript, going down this route is typically not feasible for the average user. It can also lead to other performance problems such as high admin-ajax usage and lots of uncached requests.
3. Exclude Pages From Cache (When the Cookie is Present)
Unless you can go down the JavaScript or admin-ajax route, excluding pages from caching when a specific cookie is present is the best way to go. This is typically what we recommend, especially those running highly dynamic sites such as WooCommerce and Easy Digital Downloads.
At Kinsta, certain WooCommerce and Easy Digital Downloads pages like cart, my-account, and checkout, are automatically excluded from caching. There is a server-level rule in place so that users automatically bypass the cache when the woocommerce_items_in_cart
cookie or edd_items_in_cart
cookie is detected to ensure a smooth and in-sync checkout process.
We also listen for the associated logged-in cookies and set the cache to bypass when we detect that someone has logged into WordPress. The prevents the back-end dashboard from accidentally being cached.
By default, we don’t exclude the wp_woocommerce_session_
cookie from caching. Most WooCommerce sites in our experience don’t have any issues. This also improves performance by increasing your cache HIT ratio, while utilizing fewer PHP workers.
However, due to there being many different WordPress theme and plugin configurations, we can exclude the wp_woocommerce_session_
cookie from cache if needed. Just reach out to our support team. The result is that once a user adds a product to their shopping cart, all subsequent requests won’t be served from cache, increasing the usage of PHP workers.
If you need a custom page excluded from cache, feel free to open up a ticket with our support team. Again, you have to be careful when it comes to exclusions. Too many uncached pages could really deteriorate performance. Check out our do’s and don’ts for hosting WordPress membership sites.
How to See and Clear Cookies
It’s easy to see and clear cookies on a website. To see what cookies are set on a specific site, browse to that site and click on the little padlock icon at the top. Then click on “Cookies.”
Then drill down to that website’s folder. In the example below, you can see that we have a few WooCommerce cookies set, as well as the wordpress_logged_in_[hash]
cookie. You can also see the expires time and whether it is a persistent cookie or session cookie (when the browsing session ends).
To remove a cookie, simply click on an individual cookie and click the “Remove” button. You can also do this at the folder level or in Chrome DevTools.
Clearing cookies can also help you to fix the 304 error.
Alternatively, you can search for or clear all cookies in your browser.
GDPR and Cookies
GDPR is a new privacy law that came into effect on May 25th, 2018. It was designed to give citizens back control of their personal data. We highly recommend reading our in-depth post: the lowdown on GDPR compliance if you haven’t already. This is one topic that can’t be summarized in a paragraph!
Here is an example of one change we made at Kinsta to help comply with the new law. When you first visit our site, you might have already seen it, you’re met with an “Accept Cookies” prompt at the bottom of the screen. This is because we are now legally required to provide users a way to opt-in and opt-out of cookies being set. Gone are the days of just running whatever you want without informing users of data collection.
If you click “Accept Cookies,” all cookies are then set for the user. If you click “Cookie Settings,” we now provide a way to opt-in and opt-out of whichever cookies you want.
Pretty nifty right? Our cookie solution was built in-house by our developers, but here are some helpful GDPR WordPress plugins that can help you accomplish something similar. Again, cookies are just one small part of becoming completely GDPR compliant.
PHP Sessions
PHP sessions is an alternative to the standard cookie approach. It’s still a cookie, but it’s called PHPSESSID and is typically stored in the /tmp/
directory on the web server itself. The way the server knows to associate a given session with a given request is that it’s also stored in an HTTP cookie.
This can also be seen under the HTTP header for a site.
A PHP session is much like a normal session which ends when the user closes their browser.
The problem with PHP sessions all comes down to performance and caching issues. The information stored in the browser cookie has to bounce back and forth with each request so that the server knows who the user is. This means for sites that use PHPSESSID, the host would have to set the PHPSESSID to bypass the cache. However, the result is that PHPSESSID would have to be set to bypass 100% of the time, because unlike wordpress_logged_in
, the PHPSESSID is set on every single PHP request.
So imagine that the wordpress_logged_in
had to be set 100% of the time to allow login functionality to work. Meaning that even logged-out users would have to have the cookie and it would have to be unique to them. Imagine that was required in order for the WordPress login system to work. In that scenario, every single page view would have to bypass cache so that the wordpress_logged_in
cookie was set correctly both for logged in and logged out users.
That’s the problem with using PHPSESSID. Because it’s generated on every single PHP request, if a site relies on PHPSESSID cookies the host would have to set PHPSESSID to bypass cache 100% of the time. Otherwise, the PHPSESSID’s end up cached and it messes up whatever functionality relies on it.
We don’t recommend using PHP sessions and they will usually not work in our Kinsta environment. PHP sessions also have other security implications that should be considered.
If you see code using session_start
on your site, this means its using PHP sessions.
Many plugin and theme developers have moved to using a combination of browser cookies and database rows (either in the wp_options
table or their own custom table). If you need session data this is the better approach.
Feel free to reach out to our support team if you have additional questions regarding PHP sessions.
Summary
Hopefully, now you know a little bit more about how WordPress cookies and PHP sessions work than you did before. Cookies are currently what makes the world go round and are important for pretty much everything that happens on a WordPress site. From keeping us logged in, to ensuring a smooth shopping cart experience, and even making sure that a popup window stays closed.
Have any other questions about cookies? 🍪 Let us know below in the comments.
Well written article. Explained in a detailed way and easy to understand. Thank you.
Great article, very informative, thank you.
I have one doubt about the inset:
“You can’t use WordPress without cookies”.
If i have a simple portfolio website, no comments enabled, no login, a regular user can browse my WP site w/o any cookies being created. But i might be wrong?
Hey Bogdan,
The important word in there is “use.” We assume you log in to your WordPress dashboard still to manage the content? This places a cookie. Front-end wise, it is possible to strip it down for sure.
You explanations of this stuff are the best on the web. Simple, clear, tested by a real person! Thanks so much!
Any chance you guys would consider turning your Cookie solution into a plugin? :)
We are not planning to turn it into a plugin but you know never say never :)
This is a great article. Can I just confirm two things please.
1. If an excluded cookie is detected as being used on a page, the whole page is not delivered from cache.
2. I was going to check a session variable, if it doesn’t exist, then check for a cookie, on the assumption it would be quicker to check the session variable. Are you saying, dispense with the session variable, and just use the (excluded from cache) cookie?
Many thanks
Hey Pete!
1. Yes, if a cookie such as woocommerce_items_in_cart is detected while running a WordPress/WooCommerce site at Kinsta, the entire page automatically bypasses the cache.
2. It depends on what you’re wanting to do. But excluding pages from cache using a cookie like woocommerce_items_in_cart is pretty standard practice now amongst most hosting providers.
Thanks for sharing this.
Hi,
Can someone here help to fix this problem in wordpress, woocommerce?
A PHP session was created via a call to the session_start () function. This interferes with calls via the REST API and custom calls. The session needs to be terminated using session_write_close () before making any new HTTP calls.