Embedding Widgets
Add SayWall testimonial widgets to any website in minutes using Shadow DOM or legacy iframe embed.
Updated March 12, 2026
Quick Start
Get your testimonial widget live in under 5 minutes.
In the SayWall dashboard, go to Widgets, open your widget, and click the Embed tab. Copy the two-line snippet shown there.
Paste the snippet anywhere in your page's <body>. It renders in place, so put it exactly where you want the widget to appear.
<script src="https://saywall.io/embed.min.js" async></script>
<div data-saywall-widget="YOUR_WIDGET_ID"></div>Save and reload your page. The widget loads asynchronously — it won't block your page render. You should see your approved testimonials appear within a second or two.
HTML vs React/Next.js
<!-- Place once in <head> or <body> -->
<script src="https://saywall.io/embed.min.js" async></script>
<!-- Place where you want the widget -->
<div data-saywall-widget="YOUR_WIDGET_ID"></div>The async attribute ensures the script loads without blocking your page.
How Shadow DOM Works
SayWall widgets use Shadow DOM by default. The widget renders inside an isolated shadow tree attached to your <div>, completely separate from your page's CSS.
Why Shadow DOM? Your page styles can't accidentally break the widget, and the widget styles can't leak into your page. No CSS conflicts, ever.
When embed.min.js initialises:
- It fetches the widget fragment from
https://saywall.io/w/YOUR_WIDGET_ID?shadow=1 - Attaches a shadow root to your
<div> - Injects the widget CSS + HTML into the shadow root
- Loads any required fonts or scripts (for carousel or video widgets) into the parent
<head>— deduplicated if multiple widgets share the same resource
Because the shadow root is isolated, you can embed multiple widgets on the same page without any interference.
Lazy Loading
Add data-lazyload="true" to defer the widget until it enters the viewport:
<div data-saywall-widget="YOUR_WIDGET_ID" data-lazyload="true"></div>This is useful for widgets below the fold — it skips the network request entirely until the user scrolls close to the widget. Powered by IntersectionObserver.
CSP Requirements
Content Security Policy: The Shadow DOM embed requires script-src 'unsafe-eval' in your CSP.
Add this to your Content-Security-Policy header:
script-src 'self' https://saywall.io 'unsafe-eval';
If your CSP policy prohibits unsafe-eval, use the Legacy iframe embed instead — it runs in a sandboxed iframe and does not require unsafe-eval.
Legacy iframe Embed
For sites with strict CSPs or where Shadow DOM isn't suitable, SayWall also supports a legacy iframe embed.
The iframe embed is fully supported and will continue to work. Shadow DOM is the default because it provides better visual fidelity and has no iframe-sizing quirks, but both modes are maintained.
<script src="https://saywall.io/embed.min.js" async></script>
<iframe
data-saywall-widget
src="https://saywall.io/w/YOUR_WIDGET_ID"
style="border: none; width: 100%;"
loading="lazy"
></iframe>The script automatically detects the iframe and handles height resizing via postMessage.
Frequently Asked Questions
Need help?
Have a question or need assistance? Reach us at hello@saywall.io

