What an iframe is

<iframe>, an inline frame, is an HTML tag that loads a separate document inside the current page. It is effectively a browser inside a browser: the nested document has its own DOM, its own styles and its own JavaScript execution environment.

<iframe
  src="https://payment.example.com/card-form"
  width="100%"
  height="300"
  frameborder="0">
</iframe>

The defining property: the same-origin policy forbids JavaScript inside the iframe from reaching the parent page’s DOM, cookies and localStorage when the domains differ.

Where an iframe belongs

Payment forms — the most common and best-justified case. The PCI DSS standard requires card entry fields to be isolated from the rest of the page’s code. Stripe Elements, Adyen and Braintree all build their forms on an iframe for that reason.

Video and media — YouTube and Vimeo embed only through an iframe.

Third-party chatbots and support widgets — isolation protects them from CSS and JavaScript conflicts with the host page.

Why modern recommender systems do not use iframes

Problem Consequence
A separate HTTP request for the iframe document 100-300 ms added before the widget appears
The same-origin policy blocks access to the session cookie Recommendations know nothing about the signed-in user’s profile
Events inside the iframe do not bubble to the parent A click on a recommendation is not tracked automatically
Fixed height A responsive product grid needs a JavaScript bridge over postMessage
Content invisible to search engines SEO gains none of the semantics of the recommendations

Modern personalization platforms render widgets straight into the host page’s DOM through a JavaScript SDK: the content appears in the page flow, events bubble natively and cookies are available without restriction.

postMessage: talking across the barrier

The only standard way to pass data from an iframe to its parent is the postMessage API. It is used for payment confirmations, iframe resizing and user events:

// Inside the iframe (payment.example.com)
parent.postMessage({ type: 'payment_success', amount: 24.90 }, 'https://shop.example.com');

// On the parent page (shop.example.com)
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://payment.example.com') return;
  if (event.data.type === 'payment_success') {
    // handle the payment confirmation
  }
});

Important: always check event.origin — without that check any domain can send a message into your handler.

Third-party cookie limits inside iframes

Starting with Safari and its intelligent tracking prevention, and now Chrome, third-party cookies inside an iframe are blocked by default or on their way to being blocked. In practice: if your widget on widget.vendor.com is embedded in an iframe on shop.example.com, the session cookies of widget.vendor.com will not be set or readable. That is one more argument against iframes for any widget that carries state.