Sharing cookies between sites on the same domain - Headless / Decoupled CMS Sharing cookies between sites on the same domain - Headless / Decoupled CMS wordpress wordpress

Sharing cookies between sites on the same domain - Headless / Decoupled CMS


With the clues given by @TarunLalwani (thanks a million!) in his comments, I've managed to formulate a solution.

Cookie Domain Setting

Since I was working with two seperate sites, in order for this to work I had to ensure they were both on the same domain, and that the domain was set in all cookies. This ensured cookies were included in my requests between the Node / Express server (sitting on eg. somedomain.com) and the WooCommerce CMS (sitting on eg. wp.somedomain.com), rather than being exclusive to the wp.somedomain subdomain. This was achieved by setting define( 'COOKIE_DOMAIN', 'somedomain.com' ); in my wp-config.php on the CMS.

Manually Getting and Setting Cookies

My code needed significant additional logic in order for cookies to be included whilst requests were routed through my Node / Express server through the client.

In React I had to check if the cookie existed, and if it did I had to send it through in the header of my GET request to the Node / Express server.

import Cookies from 'js-cookie';export const getSessionData = () => {  // WooCommerce session cookies are appended with a random hash.  // Here I am tracking down the key of the session cookie.  const cookies = Cookies.get();  if (cookies) {    const cookieKeys = Object.keys(cookies);    for (const key of cookieKeys) {      if (key.includes('wp_woocommerce_session_')) {        return `${key}=${Cookies.get(key)};`;      }    }  }  return false;};export const addToCart = (productId, quantity) => async (dispatch) => {  dispatch({type: ADD_TO_CART});  const sessionData = getSessionData();  const config = {};  if (sessionData) config['session-data'] = sessionData;  console.log('config', config);  try {    const payload = await axios.get(`${ROOT_API}/addtocart?productId=${productId}&quantity=${quantity}`, {      withCredentials: true,      headers: config    });    dispatch(addToSuccess(payload));  } catch (error) {    dispatch(addToCartFailure(error));  }};

On the Node / Express Server I had to check if I had included a cookie (saved in req.headers with the key session-data - it was illegal to use Cookie as a key here) from the client, and if I did, append that to the header of my request going to my CMS.

If I didn't find an appended cookie, it meant this was the first request in the session, so I had to manually grab the cookie from the response I got back from the CMS and save it to the client (setCookieFunc).

app.get('/api/addtocart', async (req, res) => {  try {    const productId = parseInt(req.query.productId);    const quantity = parseInt(req.query.quantity);    const sessionData = req.headers['session-data'];    const headers = {};    if (sessionData) headers.Cookie = sessionData;    const response = await axios.post(`${WP_API}/wc/v2/cart/add`, {      product_id: productId,      quantity    }, { headers });    if (!sessionData) {      const cookies = response.headers['set-cookie'];      const setCookieFunc = (cookie) => {        const [cookieKeyValue, ...cookieOptionsArr] = cookie.split('; ');        const cookieKey = cookieKeyValue.split('=')[0];        const cookieValue = decodeURIComponent(cookieKeyValue.split('=')[1]);        const cookieOptions = { };        cookieOptionsArr.forEach(option => (cookieOptions[option.split('=')[0]] = option.split('=')[1]));        if (cookieOptions.expires) {          const expires = new Date(cookieOptions.expires);          cookieOptions.expires = expires;        }        res.cookie(cookieKey, cookieValue, cookieOptions);      };      cookies.map(cookie => setCookieFunc(cookie));    }    return res.json(response.data);  } catch (error) {    // Handle error    return res.json(error);  }});

I'm not sure if this is the most elegant solution to the problem, but it worked for me.


Notes

I used the js-cookie library for interacting with cookies on my React client.


Gotchas

If you're trying to make this work in your development environment (using localhost) there's some extra work to be done. See Cookies on localhost with explicit domain