How to Create Communication Between Browser Tabs Using Cookies

Most of the modern desktop browsers support multi-tabbing which means that many pages can be browsed using the same application instance.

Furthermore user can run any number of browser threads which means that particular website could be displayed any number of times on different tabs. That simple and obvious fact could complicate web developer life when it comes to keep synchronized state of JS application on every tabs which sometimes is necessary.

 

That situation may occur for example with external JS plugins having different states (i.e. “minimized/maximized”, “turned on/turned off”). If user minimize window on one tab, it should be automatically minimized on every remaining tabs displaying the same website. To achieve that kind of behaviour cross-tab communication has to be implemented. There are few ways for one tab to communicate with other ones. One of them – which I will describe below – is sending messages using cookies.

At the beginning we need two simple utility functions – one for setting up a cookie with the given key (SetCookie) and the second one for reading it (GetCookie). SetCookie function besides key and value needs third parameter which is cookie lifetime measured in seconds. After that given time cookie will be destroyed by browser.


function SetCookie(key, value, seconds)
{
    var expireDate = new Date();

    expireDate.setSeconds(expireDate.getSeconds() + seconds);

    var wrappedValue = escape(value) + "; expires=" + expireDate.toUTCString() + ";
 
    path=/";

    document.cookie = key + "=" + wrappedValue;
}

function GetCookie(key)
{
    var cookiesArray = document.cookie.split(";");

    for (i = 0; i < cookiesArray.length; i++)
    {
        x = cookiesArray[i].substr(0, cookiesArray[i].indexOf("="));

        y = cookiesArray[i].substr(cookiesArray[i].indexOf("=")+1);

        x = x.replace(/^\s+|\s+$/g,"");

        if (x == key)
        {
            return unescape(y);
        }
    }
}

With those two functions we are prepared to implement cross-tab cookie communication. It would be based on three functions: SendMessage, ReadMessage and Callback. First one is called by an active tab following for example some user interaction. Second one is called recursively by every remaining tab interested in receiving the message. Callback is supplementary function doing some real stuff (like adjusting application state) and is called by ReadMessage function.


var tabID = Math.random().toString(36).substr(2, 5);

var receivedMessages = new Object();

function SendMessage(value)
{
    var messageId = Math.random().toString(36).substr(2, 5);

    var messageObject = {"sender" : tabId, "value:" : value, "messageId" : messageId};

    var messageObjectString - JSON.stringify(messageObject);

    SetCookie("someMessageKey", messageObjectString, 5000);
}

function ReadMessage()
{
    var messageObjectString = GetCookie("someMessageKey");

    if(messageObject)
    {
        var messageObject = JSON.parse(messageObjectString);

        if(messageObject.sender != tabID)
        {
            if(!receivedMessages[messageObject.messageId])
            {
                Callback(messageObject.value);
        
                receivedMessages[messageObject.messageId];
            }
        }
    }

    setTimeout(function(){ReadMessage(), 1000);
}

function Callback(value)
{
    ...
}

First notable thing in this example is tabID. It is the global, random variable unique for every tab. It will be useful to conclude which tab was the message sender. Function SendMessage composes a JSON wrapper object which contains main message value, unique message ID and tab sender ID. Afterwards it creates string from wrapper object and sets it as a cookie value. Cookie is set for 5000 ms which means that other tabs would have five seconds to receive that message.

ReadMessage function is called every one second to check for new messages. If there is any – its string value is parsed to message object. Then we can check if the message came from the same or another tab by comparing current global tabId with message object sender field. If they differ, script proceeds and checks if message with given message ID was already received. If not it calls Callback function.

Please notice some delay which would always exists because cookie value is checked in some particular intervals. In practice this delay can be considered as negligible because user have to manually switch tab to see the result of communication and it takes some time. Reducing delay by decreasing cookie lifetime and ReadMessage timeout may be not a good idea because it can consume CPU resources unnecessarily.

I hope you will find this method useful.

  • Eugene Khudoy

    It’s better to use localStorage for cross-tab communication. Here (https://github.com/slimjack/IWC ) is an inter-window communication library based on localStorage which allows to communicate between windows as between parallel processes (mutexes, shared data, eventbus…).

    • Wojciech Majerski

      Thank you for your comment Eugene. You are right – localStorage is most suitable for that but I wanted to present a method which will work also for browsers without HTML5 support. Since HTML5 support became a must for all modern browser, cookie sharing method should be treated just as a failover solution for localStorage.