How to fix embedded website issues in Workflow
Overview
This guide is for developers and site administrators who need to fix embedded website issues. If your website doesn't display correctly when viewed through Workflow (or any iframe), follow these diagnostic and fix steps.
For Workflow users: Share this article with your developer. If you're not technical, see Why isn't my embedded website working in Workflow? for a non-technical overview.
Security warning: The fixes in this guide temporarily relax certain browser security policies to allow embedding. These changes reduce protection against clickjacking and cross-origin attacks while in effect. Only apply these changes if you understand the risks, and consider reverting them after your review is complete. If your site handles payments, authentication, or sensitive user data, consult your security team before making changes.
Quick diagnosis checklist
Before diving into fixes, run through this checklist to identify the problem:
Test in an iframe locally — Create a simple HTML file with an iframe pointing to your site and check the browser console for errors
Check X-Frame-Options header — If set to
DENYor restrictiveSAMEORIGIN, your site won't embedCheck Content-Security-Policy header — Look for
frame-ancestorsrestrictionsCheck browser console for CORS errors — Look for blocked cross-origin requests in the Network or Console tabs
Check for feature-specific failures — Test PDF links, image galleries, and interactive elements separately
How to test your site in an iframe
Before making changes, reproduce the issue locally to confirm it's iframe-related:
Step 1: Create a test HTML file
Create a file called iframe-test.html with this content:
<!DOCTYPE html>
<html>
<head>
<title>Iframe Embedding Test</title>
<style>
body { margin: 0; padding: 20px; font-family: system-ui, sans-serif; }
iframe { width: 100%; height: 80vh; border: 2px solid #ccc; }
.errors { background: #fee; padding: 10px; margin-bottom: 20px; }
</style>
</head>
<body>
<h1>Testing: your-website.com</h1>
<div class="errors">
<p><strong>Console errors will appear below:</strong></p>
<p>Open DevTools (F12) and check the Console tab for CSP, CORS, and iframe errors.</p>
</div>
<iframe src="https://your-website.com" id="testFrame"></iframe>
</body>
</html>Step 2: Open in browser and check the console
Open the HTML file in Chrome, Firefox, or Edge
Press F12 to open Developer Tools
Click the Console tab
Look for red error messages (they'll tell you exactly what's blocked)
Step 3: Check the Network tab for blocked resources
Click the Network tab in DevTools
Reload the page
Filter by "blocked" or look for requests marked in red
Click blocked requests to see the specific error reason
Fix 1: Adjust X-Frame-Options
The X-Frame-Options header controls whether your site can be embedded in iframes. If it's too restrictive, your site won't load at all in Workflow.
What to check
Open DevTools, go to the Network tab, reload your page, click the main document request, and check the Headers section for X-Frame-Options.
Common values and their effects
Value | Effect | Fix |
|---|---|---|
| Site cannot be embedded anywhere | Replace with CSP |
| Can only be embedded on same domain | Replace with CSP |
| Deprecated in modern browsers | Use CSP |
Recommended fix: Use CSP frame-ancestors
The safest approach is to replace X-Frame-Options with Content Security Policy's frame-ancestors directive. This lets you specifically allow Workflow while blocking other sites:
Content-Security-Policy: frame-ancestors 'self' *.workflow.design;Why this is safer: Using *.workflow.design allows embedding only from Workflow, not from arbitrary websites. This maintains clickjacking protection while still enabling design review.
For Apache servers (.htaccess):
# Remove the old X-Frame-Options header (comment out or delete)
# Header always set X-Frame-Options "SAMEORIGIN"
# Add CSP frame-ancestors instead
Header always set Content-Security-Policy "frame-ancestors 'self' *.workflow.design;"For Nginx servers:
# Remove or comment out:
# add_header X-Frame-Options "SAMEORIGIN";
# Add CSP instead:
add_header Content-Security-Policy "frame-ancestors 'self' *.workflow.design;" always;For WordPress: Add to your theme's functions.php or use a security plugin that supports CSP:
// Remove X-Frame-Options (if set)
remove_action('send_headers', 'send_frame_options_header');
// Add CSP frame-ancestors (add to functions.php or header.php)
add_action('send_headers', function() {
header("Content-Security-Policy: frame-ancestors 'self' *.workflow.design;");
});Important: Don't remove X-Frame-Options without adding frame-ancestors as a replacement. Doing so would allow your site to be embedded on any website, including malicious ones, which creates a clickjacking vulnerability.
Fix 2: Adjust Content-Security-Policy (CSP)
Content Security Policy controls which resources can load on your site. It's the most common cause of partial failures—images loading, scripts not running, or galleries not updating.
What to check
In DevTools Network tab, reload your page, click the main document request, and find Content-Security-Policy in the Response Headers section.
Key directives to review
Directive | What it controls | Safe fix |
|---|---|---|
| Which domains can embed your site | Add |
| Where images can load from | Add your CDN domains: |
| Where scripts can load from | Add required third-party script domains (be specific) |
| Where API requests can go | Add your API endpoints specifically (avoid wildcards) |
| Where fonts can load from | Add Google Fonts, Typekit, or your CDN |
Example CSP for embedding in Workflow
Here's a secure CSP that allows Workflow embedding while maintaining protection:
Content-Security-Policy:
default-src 'self';
img-src 'self' cdn.yoursite.com data:;
script-src 'self' js.stripe.com;
style-src 'self' 'unsafe-inline';
connect-src 'self' api.yoursite.com;
frame-ancestors 'self' *.workflow.design;Avoid wildcards in production: Using * in directives like img-src, script-src, or connect-src significantly weakens your security posture. Always specify the exact domains you need rather than using wildcards, especially for scripts and API connections.
What to avoid
Don't use overly permissive CSP configurations like these:
❌ DON'T USE - This disables most CSP protections:
Content-Security-Policy: frame-ancestors *;
❌ DON'T USE - This allows any website to embed your site (clickjacking risk):
Content-Security-Policy: frame-ancestors *;
❌ DON'T USE - This allows scripts from anywhere (XSS risk):
script-src 'self' * 'unsafe-inline' 'unsafe-eval';
❌ DON'T USE - This allows API calls to any domain (data leak risk):
connect-src 'self' *;Fix 3: Resolve CORS issues
If your site loads data via AJAX/API requests (common for product variants, galleries, or dynamic content), those requests may be blocked when embedded due to Cross-Origin Resource Sharing restrictions.
Symptoms of CORS issues
Product variant images don't update
Gallery images appear blank
Dynamic content fails to load
API requests show CORS errors in console
What to check
Open DevTools → Network tab
Reload your page
Look for requests marked in red
Click the request and check for
Access-Control-Allow-Originin Response Headers
How to fix CORS safely
The safest approach is to specify allowed origins explicitly rather than using wildcards:
# Good: Specify the exact origin
Access-Control-Allow-Origin: https://app.workflow.design
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, AuthorizationFor WordPress/WooCommerce (in wp-config.php or functions.php):
// Safest: Check the origin and respond conditionally
add_action('init', function() {
$allowed_origins = ['https://app.workflow.design', 'https://workflow.design'];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowed_origins)) {
header("Access-Control-Allow-Origin: $origin");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
}
});For Apache .htaccess:
<IfModule mod_headers.c>
# Specify allowed origins explicitly
SetEnvIf Origin "https://(app\.)?workflow\.design$" ALLOWED_ORIGIN=$0
Header always set Access-Control-Allow-Origin "%{ALLOWED_ORIGIN}e" env=ALLOWED_ORIGIN
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Headers "Content-Type, Authorization"
</IfModule>Why avoid Access-Control-Allow-Origin: *: Using a wildcard allows any website to make cross-origin requests to your API. This is appropriate for public APIs, but for sites handling user data, authentication, or payments, it can expose sensitive endpoints to malicious websites. Always specify allowed origins explicitly for production sites.
Fix 4: Fix PDF links blocked in iframes
PDF links that use target="_blank" or window.open() are often blocked by browsers inside iframes. This is the most common cause of "blocked by Chrome" errors.
Symptoms
Clicking a PDF link shows "This page has been blocked" or similar error
PDF links work on your standalone site but not when embedded
New window/tab attempts fail silently
Fix: Use inline PDF embedding
Instead of opening PDFs in new windows, embed them directly in the page:
<!-- Instead of this: -->
<a href="spec-sheet.pdf" target="_blank">View Spec Sheet</a>
<!-- Option 1: Embed directly in the page -->
<embed src="spec-sheet.pdf" type="application/pdf" width="100%" height="600px">
<!-- Option 2: Object tag with fallback -->
<object data="spec-sheet.pdf" type="application/pdf" width="100%" height="600px">
<p>Unable to display PDF. <a href="spec-sheet.pdf">Download instead</a>.</p>
</object>Fix: Update WordPress/WooCommerce PDF links
For product spec sheets or downloadable files:
// In your theme or a custom plugin
// Remove target="_blank" from download links
add_filter('woocommerce_download_product_link', function($link, $product) {
return str_replace('target="_blank"', '', $link);
}, 10, 2);Fix 5: Handle image gallery issues
WooCommerce, Shopify, and other platforms often use JavaScript to load variant images. These can fail when embedded due to CSP or CORS.
Diagnose the issue
Open DevTools Console tab
Switch product variants
Look for error messages related to image loading or API calls
Common fixes
Images from CDN not loading: Add your CDN domain to img-src:
Content-Security-Policy: img-src 'self' cdn.yourdomain.com *.cloudfront.net data:;Variant API calls failing: Add your API endpoint to connect-src and configure CORS:
Content-Security-Policy: connect-src 'self' api.yourdomain.com;
Access-Control-Allow-Origin: https://app.workflow.designFix 6: Check for iframe-busting JavaScript
Some sites intentionally block iframe embedding via JavaScript that detects when the page is embedded and redirects or disables features.
What to look for
Search your JavaScript for:
// Common iframe-busting patterns
if (window.top !== window.self) { ... }
if (window.parent !== window) { ... }
if (window.self !== window.top) { ... }
if (window.frameElement) { ... }If you find code that actively blocks embedding, consider modifying it to allow Workflow specifically:
// Instead of blocking all iframes:
if (window.top !== window.self) {
window.top.location = window.self.location;
}
// Allow embedding from Workflow:
try {
if (window.top !== window.self) {
const isWorkflow = window.location.ancestorOrigins?.[0]?.includes('workflow.design');
if (!isWorkflow) {
// Only bust out of non-Workflow embedders
window.top.location = window.self.location;
}
}
} catch (e) {
// Cross-origin access blocked - safe to stay embedded
}WordPress and WooCommerce checklist
If you're running WordPress with WooCommerce, check these common issues:
Security plugin settings — Plugins like Wordfence, iThemes Security, or Jetpack may set restrictive
X-Frame-Optionsor CSP headers. Check plugin settings for "iframe" or "embedding" options.CDN configuration — If using Cloudflare or similar, check if the CDN adds security headers that block images or scripts.
Theme or plugin JavaScript — Some themes have iframe-busting code. Search theme files for
window.toporwindow.parentchecks.WooCommerce AJAX endpoints — Ensure your REST API endpoints have proper CORS headers for variant and gallery requests.
WP Rocket or caching plugins — Some caching plugins add optimization headers that interfere with embedding. Check for "security" or "optimization" settings.
After your review is complete
Once your design review is finished, consider re-enabling stricter security policies:
Restore
X-Frame-Options: SAMEORIGINif you removed it (or keepframe-ancestors 'self'in CSP)Remove
*.workflow.designfromframe-ancestorsif you no longer need embeddingReview any CORS changes and revert overly permissive settings
Alternative workaround: If security policy changes are not appropriate for your production site, consider using a staging environment with relaxed settings specifically for design review, or use Workflow's screenshot and screen recording features instead of embedding the live site.
Testing after making changes
After making any of the fixes above:
Clear any caches (browser, CDN, WordPress caching plugins)
Open your
iframe-test.htmlfile in a fresh browser tabOpen DevTools Console and Network tabs
Reload and check for any remaining errors
Test all features: navigation, forms, image galleries, PDF links, and any interactive elements
If everything works in your local iframe test, it will work in Workflow as well.
Still having issues?
If you've tried these fixes and problems persist:
Gather console errors and network request failures from your browser's DevTools
Note which features work on your standalone site but fail when embedded
Include your server type (Apache, Nginx, etc.) and any security plugins you're using
Contact [email protected] and we'll take a look.
Related articles: For a non-technical overview of embedded website issues, see Why isn't my embedded website working in Workflow?