Explain Codes LogoExplain Codes Logo

How to communicate between iframe and the parent site?

javascript
cross-domain-communication
event-listeners
message-handling
Alex KataevbyAlex Kataev·Jan 16, 2025
TLDR

Harness the potential of the window.postMessage() method for a secure and two-way communication between an iframe and its parent page. Kickstart the conversation from the child iframe using parent.postMessage(message, targetOrigin) or from the parent using iframe.contentWindow.postMessage(message, targetOrigin). Always create an event listener that filters incoming messages, checking event.origin and processing event.data.

Quick setup garlic bread recipe (jk, it's code):

// Parent to iframe -> "Hello iframe!", analogous to "Luke, I am your father" document.getElementById('myIframe').contentWindow.postMessage('Hello iframe!', '*'); // Iframe listens, like a good child should window.addEventListener('message', event => { if (event.origin !== window.location.origin) return; // Ignore strangers alert(`My parent says: ${event.data}`); }, false);

For a cheeky bit of extra security, sneakily replace '*' with your explicit targetOrigin - this ain't no open house, it's private property!

A comprehensive guide: making iframe and parent talk secure

Target Origin: not all * are lucky ones!

Using '*' as the target origin in postMessage() is like keeping your front door wide open - anyone can walk in! Specify an exact URL to keep out those pesky intruders:

// It's like giving your home address to your trusted friend iframe.contentWindow.postMessage('Hello Iframe!', 'https://example.com');

Communication posturing: from iframe to parent

Modern browsers came up with this fancy new thing where a CustomEvent is used in the iframe to pass a message to the parent:

// Summon a custom event within the iframe, like casting a spell in Hogwarts var customEvent = new CustomEvent('owlPost', { detail: 'Here is the snitch' }); parent.document.dispatchEvent(customEvent);

Now, the parent can wait for its Hogwarts letter:

window.addEventListener('owlPost', function(e) { console.log('Message from Hogwarts:', e.detail); });

Pack those messages neatly: message classes

Create a dandy message box to pack your messages neatly. Simply have a type and a body property. It's great to organize your thoughts (read: communication):

class OwlPost { constructor(type, body) { this.type = type; this.body = body; } }

Packed and stacked messages make life easier.

Event.data isn’t always truth

So you got a shiny message - great! But can you trust it? Is it from Voldemort? Always, and I mean always, verify the origin and structure of message:

window.addEventListener('message', event => { if (event.origin !== 'https://hogwarts.com') return; // Don't take candies from strangers if (!event.data.type || !event.data.body) return; // Validate the owl's post handleOwlPost(event.data); });

OwlPost by name and by nature: sendMessage function

Keep a consistent experience for your owls - use a sendMessage function:

// Trusty OwlPost carrier function sendMessage(owl, message, targetOrigin) { owl.contentWindow.postMessage(message, targetOrigin); }

Different owls for different times

Adopt different owls for different types of messages, to breeze through your event handling process:

const owlHandlers = { 'Hedwig': handleHedwigPost, 'Errol': handleErrolPost, }; function handleOwlPost(message) { if (messageHandlers[message.type]) { messageHandlers[message.type](message.body); // Different owls, different wonders } }

Paving your way: Best practices and tools

Browser compatibility: Who supports what?

Before you summon the postMessage magic, get your browser compatibility sensation on check. IE8+ has got you covered, but why not reassure with a quick visit to Can I use.

Cross-domain communication: You'll need a permit

When having a chat with an iframe from another domain, have this handy JS file on a CDN bat-signal. It's even more essential when your subdomain puts up boundaries.

Message categorisation: in light of efficiency

Be organised in your messages - categorise them by type, source and the purpose:

{ type: 'notification', source: 'iframe', purpose: { message: 'User has accepted the terms.' } }

Increasing security: beyond checking the event origin

When you're turning over every rock for security, try these:

  • Peek under the event.source, check that it matches the anticipated window.
  • If your postMessage deals with classified info, cryptographic checks are going to be your new best friend.

All in the palm of your hand: Bundle your complex data

You've got this complex data to send, and it's all a tangled mess? Use JSON encoding, just wrap the parsing in a try-catch:

window.addEventListener('message', event => { try { const data = JSON.parse(event.data); // Handle the data... } catch (error) { console.error('Parser slipped on a banana peel', error); } });

A message every second: batching updates

Real-time interactions might require high-frequency messages. Put on a pot of coffee and start batch DOM updates or use requestAnimationFrame to slim down on reflows/repaints.