Enable Embedding for Testing
Your site is blocking preview embeds. Here's how to fix it — or work around it.
Test Your Embed
Want to check if your iframe is working? Enter your URL below:
Why This Happens
Most modern websites block embedding by default to prevent clickjacking attacks. This is controlled by HTTP headers like X-Frame-Options and Content-Security-Policy.
If you own the site, enabling embedding takes about 1 minute. If you don't, there are workarounds below.
For Developers (1-Minute Fix)
Add a Content-Security-Policy header that allows embedding from our domain. Choose your framework below.
Next.js
Add to your next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'Content-Security-Policy',
value: "frame-ancestors 'self' https://zebra.day;"
}
]
}
];
}
};
module.exports = nextConfig;Vercel
Add to your vercel.json:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "Content-Security-Policy",
"value": "frame-ancestors 'self' https://zebra.day;"
}
]
}
]
}Netlify
Add to your netlify.toml:
[[headers]]
for = "/*"
[headers.values]
Content-Security-Policy = "frame-ancestors 'self' https://zebra.day;"Or add a _headers file in your publish directory.
Express.js / Node.js
// Using helmet
const helmet = require('helmet');
app.use(
helmet({
contentSecurityPolicy: {
directives: {
frameAncestors: ["'self'", "https://zebra.day"]
}
},
frameguard: false
})
);
// Or manual middleware
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"frame-ancestors 'self' https://zebra.day"
);
next();
});Other Frameworks (Django, Rails, Laravel)
Django
# settings.py
MIDDLEWARE = [
'myapp.middleware.FrameAncestorsMiddleware',
# Remove XFrameOptionsMiddleware
]
# myapp/middleware.py
class FrameAncestorsMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
response['Content-Security-Policy'] = (
"frame-ancestors 'self' https://zebra.day"
)
return responseRuby on Rails
# config/initializers/content_security_policy.rb
Rails.application.config.content_security_policy do |policy|
policy.frame_ancestors :self, "https://zebra.day"
endLaravel
// app/Http/Middleware/SecurityHeaders.php
public function handle($request, $next)
{
$response = $next($request);
$response->headers->set(
'Content-Security-Policy',
"frame-ancestors 'self' https://zebra.day"
);
return $response;
}Security Note
Only whitelist domains you trust. Using frame-ancestors * allows any site to embed yours, which can enable clickjacking attacks.
For Designers
Design tools like Figma have built-in embedding that works without any configuration.
Figma Prototypes
Figma prototypes embed directly — no code changes needed.
- 1. Open your Figma file
- 2. Click Share → set to “Anyone with the link can view”
- 3. Click the prototype tab and copy the prototype link
- 4. Paste the link when creating your test in Zebra
Prototype URL format:
https://www.figma.com/proto/FILE_KEY/...Other Design Tools
| Tool | Embed Support |
|---|---|
| Figma | Works out of the box |
| Framer | Works with share link |
| ProtoPie | Works with cloud link |
| Adobe XD | Limited (being phased out) |
Don't Own the Site?
If you can't modify the site's headers, here are your options.
Convert the Website to a Figma Prototype
Use html.to.design by ‹div›RIOTS to capture any website as an editable Figma file.
- 1. Install the html.to.design Chrome extension
- 2. Navigate to the website you want to test
- 3. Click the extension → “Capture Page”
- 4. Open Figma and install the html.to.design Figma plugin
- 5. Import the captured file into Figma
- 6. Add prototype interactions if needed
- 7. Share the Figma prototype link in Zebra
Best for: Testing visual design, navigation, and first impressions. The prototype won't have real functionality but works great for click-through tests.
Screenshot Key Screens → Build in Figma
Capture full-page screenshots and assemble them as a clickable Figma prototype.
- 1. Use a tool like ScreenshotOne, Urlbox, or browser DevTools to capture full-page screenshots
- 2. Import screenshots into Figma as frames
- 3. Add hotspot links between frames to create navigation
- 4. Share the prototype link in Zebra
Best for: Quick tests when you only need a few key screens, or when html.to.design doesn't capture the page correctly.
Automated Capture with Playwright
For technical users: use Playwright to capture screenshots or recordings of user flows, then convert to a Figma prototype.
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
// Capture a flow
await page.goto('https://target-site.com');
await page.screenshot({
path: '01-homepage.png',
fullPage: true
});
await page.click('button.signup');
await page.screenshot({
path: '02-signup.png',
fullPage: true
});
await page.fill('input[name="email"]', 'test@example.com');
await page.screenshot({
path: '03-form-filled.png',
fullPage: true
});
await browser.close();Best for: Capturing complex flows with multiple states, authenticated pages, or dynamic content.
Testing Your Changes
After adding the headers, verify embedding works:
- 1. Deploy your changes
- 2. Open browser DevTools → Network tab
- 3. Load your site and click on the main document request
- 4. Check Response Headers for
Content-Security-Policy - 5. Verify it includes
frame-ancestors 'self' https://zebra.day
Then try creating a new test in Zebra — the preview should load correctly.
Still Having Issues?
Some common gotchas:
- CDN caching: Headers might be cached. Try purging your CDN cache or wait a few minutes.
- Multiple CSP sources: If you have other CSP directives, make sure
frame-ancestorsisn't being overwritten. - Hosting platform defaults: Some platforms set restrictive defaults. Check your platform's security settings.
- Localhost testing: If testing locally, embedding usually works fine — the issue is typically only on production.