Troubleshooting

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 DENY or restrictive SAMEORIGIN, your site won't embed

  • Check Content-Security-Policy header — Look for frame-ancestors restrictions

  • Check 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

  1. Open the HTML file in Chrome, Firefox, or Edge

  2. Press F12 to open Developer Tools

  3. Click the Console tab

  4. Look for red error messages (they'll tell you exactly what's blocked)

Step 3: Check the Network tab for blocked resources

  1. Click the Network tab in DevTools

  2. Reload the page

  3. Filter by "blocked" or look for requests marked in red

  4. 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

DENY

Site cannot be embedded anywhere

Replace with CSP frame-ancestors (see below)

SAMEORIGIN

Can only be embedded on same domain

Replace with CSP frame-ancestors for granular control

ALLOW-FROM uri

Deprecated in modern browsers

Use CSP frame-ancestors instead

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

frame-ancestors

Which domains can embed your site

Add *.workflow.design alongside 'self'

img-src

Where images can load from

Add your CDN domains: img-src 'self' cdn.yoursite.com data:

script-src

Where scripts can load from

Add required third-party script domains (be specific)

connect-src

Where API requests can go

Add your API endpoints specifically (avoid wildcards)

font-src

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

  1. Open DevTools → Network tab

  2. Reload your page

  3. Look for requests marked in red

  4. Click the request and check for Access-Control-Allow-Origin in 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, Authorization

For 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.

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>

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);

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

  1. Open DevTools Console tab

  2. Switch product variants

  3. 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.design

Fix 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-Options or 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.top or window.parent checks.

  • 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: SAMEORIGIN if you removed it (or keep frame-ancestors 'self' in CSP)

  • Remove *.workflow.design from frame-ancestors if you no longer need embedding

  • Review 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:

  1. Clear any caches (browser, CDN, WordPress caching plugins)

  2. Open your iframe-test.html file in a fresh browser tab

  3. Open DevTools Console and Network tabs

  4. Reload and check for any remaining errors

  5. 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?

Was this helpful?