The simplest way to overlay third‑party content in your flipbooks via GTM
Table of contents
- Overview
- Step-by-step instructions
- Optional: Add iframe as a modal pop-up
- Additional tips / FAQs
- Common use-cases
- Troubleshooting
- Next steps
Overview
If you want to display third‑party content (chatbots, forms, banners) over your Flipsnack flipbooks, use Google Tag Manager (GTM) to inject a lightweight overlay. You’ll manage everything from GTM without editing the flipbook itself.
Important: Overlays appear on top of the flipbook player, not inside the flipbook pages. They can show automatically (banner) or on demand (button → modal).
How to create a Custom HTML tag in GTM
Before pasting any of the code examples, you’ll need to create a Custom HTML tag inside your Google Tag Manager container.
-
Log in to Google Tag Manager and select the container used for your flipbooks.
-
In the left-hand menu, click Tags.
-
Click New → name your tag (for example, Flipbook iframe overlay).
-
Click Tag Configuration → choose Custom HTML.
-
Paste the code snippet provided in this guide.
-
Scroll down to Triggering → click + to add a new trigger.
-
Choose Page View.
-
Select DOM Ready (recommended).
-
(Optional) Add a filter so it only fires on your flipbook URLs (e.g., Page URL contains flipsnack.com).
-
-
Click Save.
-
When you’re ready, click Submit and Publish in GTM to apply your changes.
Tip: Always preview your container changes with GTM’s Preview mode before publishing. This lets you confirm the overlay works correctly on your flipbook link.
Step-by-step instructions
Quick start (2 minutes): Paste‑and‑go overlay
Simplest path: Copy this into a Custom HTML tag in GTM, set the trigger to DOM Ready, and change only YOUR_FORM_URL
.
<script>
(function(){
// Change just this:
var YOUR_FORM_URL = 'https://yourform.typeform.com/to/abc123'; // ⬅️ only change this
try { if (window.self !== window.top) return; } catch(e) { return; }
if (window.__fsOverlayOnce) return; window.__fsOverlayOnce = true;
function inject(){
if (document.getElementById('fs-quick-overlay')) return;
var box = document.createElement('div');
box.id = 'fs-quick-overlay';
box.style.cssText = 'position:fixed;bottom:12px;right:12px;width:300px;height:400px;'+
'background:#fff;box-shadow:0 0 10px rgba(0,0,0,.3);z-index:2147483647;';
var iframe = document.createElement('iframe');
iframe.src = YOUR_FORM_URL;
iframe.style.cssText = 'width:100%;height:100%;border:none;';
var close = document.createElement('button');
close.type='button';close.textContent='×';
close.setAttribute('aria-label','Close');
close.style.cssText='position:absolute;top:6px;right:6px;background:#000;color:#fff;border:none;'+
'cursor:pointer;padding:4px 8px;font-size:14px;line-height:1;';
close.addEventListener('click', function(){ box.remove(); });
box.appendChild(iframe); box.appendChild(close);
(document.body||document.documentElement).appendChild(box);
}
if (document.readyState==='loading') document.addEventListener('DOMContentLoaded', inject); else inject();
})();
</script>
That’s it. No other edits needed. To move the box, change bottom
/right
values; to resize, change width
/height
.
Optional (more control): Overlay with simple settings
Paste this one-file overlay script in GTM (Custom HTML, trigger: DOM Ready)
Why this is easy: All the settings you might change live in the CONFIG
block at the top.
<script>
(function(){
// ================== SIMPLE CONFIG ==================
var CONFIG = {
formUrl: 'https://yourform.typeform.com/to/abc123', // <— change to your URL
size: { width: '300px', height: '400px' }, // <— change size
pos: { bottom: '10px', right: '10px' }, // <— change position
zIndex: 2147483647 // stays above player
};
// ==================================================
// 1) Run only in top window (avoid inner iframes)
try { if (window.self !== window.top) return; } catch(e) { return; }
// 2) Prevent duplicates
if (window.__fsOverlayInjected) return;
window.__fsOverlayInjected = true;
function css(obj){ return Object.keys(obj).map(function(k){return k+':'+obj[k]}).join(';'); }
function inject(){
if (document.getElementById('fs-iframe-overlay')) return;
var wrap = document.createElement('div');
wrap.id = 'fs-iframe-overlay';
wrap.setAttribute('role','dialog');
wrap.style.cssText = [
'position:fixed',
'background:#fff',
'border:none',
'box-shadow:0 0 10px rgba(0,0,0,0.3)',
'width:'+CONFIG.size.width,
'height:'+CONFIG.size.height,
'z-index:'+CONFIG.zIndex,
css(CONFIG.pos)
].join(';');
var iframe = document.createElement('iframe');
iframe.src = CONFIG.formUrl;
iframe.title = 'Embedded form';
iframe.style.cssText = 'width:100%;height:100%;border:none;';
var btn = document.createElement('button');
btn.type = 'button';
btn.setAttribute('aria-label','Close overlay');
btn.textContent = '×';
btn.style.cssText = 'position:absolute;top:6px;right:6px;background:#000;color:#fff;border:none;cursor:pointer;padding:4px 8px;font-size:14px;line-height:1;';
btn.addEventListener('click', function(){ wrap.remove(); });
wrap.appendChild(iframe);
wrap.appendChild(btn);
(document.body || document.documentElement).appendChild(wrap);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', inject);
} else {
inject();
}
})();
</script>
GTM settings
-
Tag type: Custom HTML
-
Trigger: Page View → DOM Ready (fallback: Window Loaded)
-
Filter: Limit to your flipbook URLs (e.g., Page URL contains your flipbook path)
-
Firing options (if available): Once per page
Optional: Add iframe as a modal pop-up
Prefer a modal that opens on demand? Choose one of the two easy options below.
Auto-open modal (script-only)
Paste as Custom HTML in GTM (trigger: DOM Ready). Change only the CONFIG.formUrl
if needed.
<script>
(function(){
var CONFIG = { formUrl: 'https://yourform.typeform.com/to/abc123' };
try { if (window.self !== window.top) return; } catch(e) { return; }
if (window.__fsPopupInjected) return; window.__fsPopupInjected = true;
function create(){
if (document.getElementById('fs-popup')) return;
var wrap = document.createElement('div');
wrap.id = 'fs-popup';
wrap.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;'+
'background:rgba(0,0,0,0.5);z-index:2147483647;display:flex;justify-content:center;align-items:center;';
var inner = document.createElement('div');
inner.style.cssText = 'position:relative;width:400px;height:500px;background:#fff;padding:10px;';
var iframe = document.createElement('iframe');
iframe.src = CONFIG.formUrl;
iframe.style.cssText = 'width:100%;height:100%;border:none;';
var btn = document.createElement('button');
btn.type = 'button';
btn.setAttribute('aria-label','Close popup');
btn.textContent = '×';
btn.style.cssText = 'position:absolute;top:10px;right:10px;background:#000;color:#fff;border:none;cursor:pointer;padding:4px 8px;font-size:16px;line-height:1;';
btn.addEventListener('click', function(){ wrap.remove(); });
inner.appendChild(iframe);
inner.appendChild(btn);
wrap.appendChild(inner);
(document.body || document.documentElement).appendChild(wrap);
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', create); else create();
})();
</script>
Add a persistent top banner (recommended)
Use this option when you want a clear, non-intrusive way to let readers open a form. The banner sits at the top of the flipbook player and includes a CTA that launches the modal. No edits are needed inside the flipbook.
GTM → Custom HTML (trigger: DOM Ready)
<script>
(function(){
var CONFIG = {
formUrl: 'https://yourform.typeform.com/to/abc123', // change to your URL
bannerText: 'Need help? Open form', // CTA label
bannerHeight: 64, // px
zIndex: 2147483647
};
try { if (!/\.flipsnack\.com$/i.test(location.hostname)) return; } catch(e) { return; }
if (window.__fsBannerOnce) return; window.__fsBannerOnce = true;
function ensureModal(){
if (document.getElementById('fs-popup')) return;
var wrap=document.createElement('div');
wrap.id='fs-popup';
wrap.style.cssText='display:none;position:fixed;top:0;left:0;width:100%;height:100%;'+
'background:rgba(0,0,0,0.5);z-index:'+CONFIG.zIndex+';justify-content:center;align-items:center;';
var inner=document.createElement('div');
inner.style.cssText='position:relative;width:420px;height:560px;background:#fff;padding:10px;';
var iframe=document.createElement('iframe');
iframe.src=CONFIG.formUrl; iframe.style.cssText='width:100%;height:100%;border:none;';
var btn=document.createElement('button');
btn.type='button'; btn.setAttribute('aria-label','Close'); btn.textContent='×';
btn.style.cssText='position:absolute;top:10px;right:10px;background:#000;color:#fff;border:none;cursor:pointer;padding:4px 8px;font-size:16px;line-height:1;';
btn.addEventListener('click', function(){ wrap.style.display='none'; });
inner.appendChild(iframe); inner.appendChild(btn); wrap.appendChild(inner);
(document.body||document.documentElement).appendChild(wrap);
}
function showModal(){ ensureModal(); var el=document.getElementById('fs-popup'); if(el) el.style.display='flex'; }
function injectBanner(){
if (document.getElementById('fs-top-banner')) return;
var bar=document.createElement('div');
bar.id='fs-top-banner';
bar.style.cssText='position:fixed;left:0;right:0;top:0;height:'+CONFIG.bannerHeight+'px;'+
'display:flex;align-items:center;justify-content:center;background:#111;color:#fff;'+
'font:500 14px/1.2 system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;z-index:'+CONFIG.zIndex+';';
var cta=document.createElement('button');
cta.type='button'; cta.textContent=CONFIG.bannerText;
cta.style.cssText='margin-left:8px;padding:8px 12px;border:none;border-radius:6px;background:#00AEEF;color:#fff;cursor:pointer;';
cta.addEventListener('click', showModal);
var close=document.createElement('button');
close.type='button'; close.textContent='×'; close.setAttribute('aria-label','Dismiss banner');
close.style.cssText='position:absolute;right:10px;top:50%;transform:translateY(-50%);background:transparent;color:#fff;border:none;cursor:pointer;font-size:18px;';
close.addEventListener('click', function(){ bar.remove(); });
bar.appendChild(cta); bar.appendChild(close);
(document.body||document.documentElement).appendChild(bar);
}
function init(){ injectBanner(); ensureModal(); }
if (document.readyState==='loading') document.addEventListener('DOMContentLoaded', init); else init();
})();
</script>
Additional tips / FAQs
Can I target different flipbooks with different forms? Yes. In GTM, use URL-based triggers and duplicate the tag with different CONFIG.formUrl
values.
Can I delay the overlay? Yes. Wrap the inject()
/create()
call in setTimeout(function(){ ... }, 8000)
(for 8s).
Can I track interactions inside the iframe? Only if you control the iframe source and add tracking code there.
Common use-cases
-
Chat widgets (Intercom, Zendesk)
-
Feedback or survey forms (Typeform, Google Forms)
-
Campaign banners and offers
-
Lead capture and conversions
Troubleshooting
Overlay/modals don’t show
-
Confirm GTM publishes and the trigger = DOM Ready.
-
Check that the tag fires only on your flipbook URLs.
-
Open DevTools → Elements to see whether the node exists.
It loads twice
-
Keep the top-window guard and global flags included above (
window.self===window.top
,__fsOverlayInjected
,__fsPopupInjected
). -
Optional in GTM: create a JS – IsInIframe variable and add it as a Trigger Exception.
Overlay covers player controls
-
Tweak size/position in
CONFIG
(e.g., bigger bottom/right values).
Iframe refused to connect
-
The source may set
X-Frame-Options
/CSP
to block embedding. Try another provider or host your own page.
Next steps
Useful resources
- Customize the flipbook player
- Set up Google Tag Manager in your flipbooks
- Set up Google Tag Manager in Flipsnack
Need expert support?
Our team is here to help. Connect with our team experts or message us via the in-app chat for a personalized assistance.