iframe.js

Last updated October 1, 2021 by Jacob Paris

This is a helper script to allow an embedded iframe to communicate with its parent page.

Place this on the page that contains the <iframe

The script

  • Listens for triggers emitted by application
  • Triggers scrolling on parent page
  • Triggers positions and resize iframe to fit content
  • Triggers opening of new pages
  • Passes UTM codes into iframe via URL query
jsiframe.js
1;(function (frameId) {
2 let connected = false
3
4 if (document.readyState === 'loading') {
5 document.addEventListener('readystatechange', addEventListenersToDocument)
6 } else {
7 addEventListenersToDocument()
8 }
9
10 function addEventListenersToDocument() {
11 if (connected) return
12
13 // The iframe with the funnel must have the following ID
14 const portal = document.getElementById(frameId)
15
16 // Set initial height to reduce jarring size changes
17 portal.style['min-height'] = '100vh'
18
19 window.addEventListener('message', function (e) {
20 // Resize iframe to fit contents
21 if (e.data.type && e.data.type === 'size') {
22 portal.style['min-height'] = e.data.height + 'px'
23 }
24
25 // Scroll parent page to top
26 if (e.data.type && e.data.type === 'scrolltop') {
27 document.body.scrollIntoView(e.data.options)
28 }
29
30 // Scroll parent page by X (Up, Down, Left or Right)
31 if (e.data.type && e.data.type === 'scrollby') {
32 // Make movements better on mobile
33 e.data.options.top =
34 window.innerHeight < e.data.options.top
35 ? window.innerHeight / 3
36 : e.data.options.top / 2
37 // Need to check to see if the browser supports smooth scroll
38 // otherwise use legacy scroll
39 if ('scrollBehavior' in document.documentElement.style) {
40 window.scrollBy(e.data.options)
41 } else {
42 window.scrollBy(e.data.options.left, e.data.options.top)
43 }
44 }
45
46 // Click link inside of iframe
47 if (e.data.type && e.data.type === 'link') {
48 window.open('./' + e.data.path.replace(new RegExp('^/'), ''), '_blank')
49 }
50 })
51
52 // Extract utm codes from query string
53 const parentUrl = new URL(window.location.href)
54 const urlCodes = Object.fromEntries(
55 Array.from(parentUrl.searchParams.entries()).filter(([key]) =>
56 key.startsWith('utm_'),
57 ),
58 )
59
60 const utmCodes = {
61 ...urlCodes,
62 }
63
64 // Assign utm codes to iframe query string
65 const portalUrl = new URL(portal.src)
66
67 Object.entries(utmCodes).forEach(([key, code]) => {
68 portalUrl.searchParams.append(key, code)
69 })
70
71 portal.src = portalUrl.href
72 connected = true
73
74 document.removeEventListener(
75 'readystatechange',
76 addEventListenersToDocument,
77 )
78 }
79})('FRAME_ID')
80

Usage

Replace 'FRAME_ID' at the bottom of the script with the id of the iframe you want to embed.

Embed the iframe with the same ID and the following script

<script src="./iframe.js"></script>
<iframe
id="FRAME_ID"
src="https://example.com"
style="border: 0px; width: 100%; margin: 1rem 0rem 2rem; min-height: 45rem;"
allowfullscreen="true"
sandbox="allow-same-origin allow-scripts allow-top-navigation-by-user-activation allow-popups allow-popups-to-escape-sandbox allow-forms"
scrolling="no"
width="100%"
height="100%"
></iframe>