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.