Cross-Domain Iframe-parent communication

Farzad YZ
2 min readDec 28, 2016

--

Fair warning: This solution worked for the certain use case explained in the article back in 2016, the same date this very article was published. It might not work right now!

There are many cases iframe would be a good solution to use. Although they are kind of dead to HTML and not a lot of developers use it, It could come up to you as a solution to a complicated problem some day.

Knowing a way to communicate through an iframe to parent is such a valuable and time saver. Maybe iframe could tell it’s parents when it’s content is ready or engage user interactions inside the iframe with the parent to react properly.

Some days ago at my company, we had a Wordpress website that loaded an iframe for choosing a plan to buy virtual machines as shown below.

An iframe included inside Wordpress to choose VM plans

I was assigned a task to do something challenging on this element. The company intended to open a URL on click of the orange button, BUT because the button was inside the iframe, that couldn’t be managed easily.

First thing I tried to was to use postMessage to send a message from iframe to its parent. I came up with this code:

<iframe src="Path/To/Html"><button id="my-btn">Start</button></iframe>

document.getElementById('my-btn').addEventListener('click', handleButtonClick, false);function handleButtonClick(e) {  window.parent.postMessage('iframe_message')
}

And also listen to the message on the parent window:

window.addEventListener('iframe_message', function() {  window.open('some url', '_blank')
}, false);

It was perfect! worked like a charm. It passed some minutes until I figured out the actual problem. This only worked for same-domain iframes. Apparently, cross-domain iframes don’t post the message to the parent properly.

I dogged the web a lot and found a really interesting inspiration on a dark edge of StackOverflow. Although It did not help me, It fixed me in the right direction. The solution was to use custom events.

So I refactored the solution to:

document.getElementById('my-btn').addEventListener('click', handleButtonClick, false);var myEvent = new CustomEvent('my_event', { detail: {url: 'some url'} })function handleButtonClick(e) {window.parent.dispatchEvent(myEvent)
}

And listen to it on the parent of course:

window.addEventListener('iframe_message', function(e) {var url = e.detail.urlwindow.open(url, '_blank')
}, false);

It was amazing as I could easily pass custom data from iframe to the parent window.

Conclusion:

Dealing with iframes is Hard. It’s not intended to be used unless there is no other way to do it.

If you’re using a same-domain iframe, you’re in heaven. You could easily control iframe’s content and also communicate with its parent through postMessage.

But you’re in Hell when it gets cross-domain. You could only use CustomEvent and dispatchEvent on the iframe and listen to it on the parent window. In this case, try to modularize your communication protocol and pass custom data.

--

--

Farzad YZ

Senior Software Engineer @epicgames . formerly @futurice . Javascript, Typescript, React(native), International speaker. UI engineering, Statecharts, Reactivity