postMessage: communication between browser tabs

Swaraj Rajpure
4 min readSep 7, 2021

--

Ever wondered how could one tab opens up another tab and they communicate with each other? Maybe you go to buy something on some site, now that site might open a new tab for processing your payment and if you try going back to the first tab/main site, you would see that the page has some sort of timer running. How does that page know that you have or have not completed the payment yet? That too which is taking place in other tab? How do these two tab communicate with each other? The answer is using postMessage browser API and message event listener.

What’s happening here is that your main site is opening the payment page in a new tab mostly using window.open() method. How will the new tab refer to the main tab which opened it? You can refer that window using window.opener. As the name suggests, it simply points to the window object which caused this new tab to open. Main site would have started some sort of timer as soon as this new page is opened, saying something like Please complete the transaction in 5:00 minutes or so.

Your new tab obviously knows if you’re done with the payment or not. Now once you complete the payment on this tab, main site should know that. Here comes the interesting part of postMessage. This new tab will post a message to the window which opened it, using postMessage API, indicating that the payment is now complete. Okay, this tab has done its job, but how does the main site get to know this?

Listening for message 😛

There’s an event called message which this main site would be listening to (just like how we listen to click events). As soon as the main site receives the message which contains valid payload/data of the payment being completed, the UI would redirect you to maybe tracking details of that particular thing.

Enough of theory, right? Let’s get coding!

Here’s our index.html, nothing fancy going on here. Just one button and simple text. Do focus on the span though, we’re going to play with it 😉

This is what we see:

Here’s the corresponding JavaScript code. Clicking on the button should disable it and a new tab should open with payment.html

Now we need to know how the payment.html looks like, right? Just one single button to replicate the behaviour as if the user has completed the payment (over-simplification 😬)

Here’s what this HTML renders:

Here’s the corresponding JavaScript code. On clicking the button, we’re sending a postMessage to the window.opener with the payload which confirms that the payment has completed. Finally we close this tab.

But hey! How does our main page get to know that the payment has succeeded? We haven’t written any logic for it yet! Let’s add that to our index.js

Now we have added an event listener for message event. Once the user clicks on the button on the other tab, we’re triggering a message, right? As soon as this tab receives a message, it opens up the e or event object and looks inside it for data.isPaymentCompleted. Once that’s done, we know the user has completed their payment and we modify the UI content. Remember we had talked about the span earlier? We’re now making it’s textContent to be true 😉

Here is the hosted demo: https://swaraj-postmessage-demo.netlify.app. Here’s the GitHub repo if you want to have a look: https://github.com/swarajpure/postMessage-demo

This might not have been a very good example, since we shouldn’t be dependent only on frontend for functionalities which are as delicate as payments, we should have checks from backend as well. Nonetheless, I guess you get the point I was trying to make and hope that you would have learnt something new 😄

Thank you! 🎉

--

--