Skip to content

Website with SDK cannot be used inside of an iframe (other than WS) #16

@vladbulyukhin

Description

@vladbulyukhin

Motivation

Right now if the website connected to the SDK is run inside of an iframe (other than WS), the redirect feature and Web Spotlight features (enable/disable editable elements, in-context editor, etc.) won't work. This happens because the SDK assumes that the iframe, it is being run inside of, is a Web Spotlight preview iframe and tries sending messages to this iframe which are left unprocessed. Currently, there is no way to override this behavior.

Proposed solution

First of all, we need to decide whether we want to somehow fix this issue or not. There are several possible solutions that can be used to solve it:

  • We can add a boolean flag to the SDK configuration object that will allow users to disable the iframe communication. This way when someone wants to wrap a website connected to the SDK with an iframe, they can disable the iframe communication feature and smart links will always open Kontent in a new tab instead of sending iframe messages. The main disadvantage of this method is that without the iframe communication smart links will open Kontent in a new tab even in Web Spotlight because Web Spotlight requires iframe communication to work properly.
  • We can add some public helpers to SDK that will help users with this problem (more information about this can be found in the Workaround section of this issue).

Workaround

If you plan on using the website (connected to the SDK) inside of an iframe, you can use this workaround to make everything work properly with Web Spotlight.

The first thing you need to do is listen to all message events on your host page window object.

window.addEventListener('message', handleMessage);

Then whenever you receive a new message, you need to check whether it is a message related to SDK. If it is related to the SDK, you need to check if you are currently inside an iframe and if you aren't, you just generate a smart link (using buildKontentLink helper from @kentico/kontent-smart-link) and open it in a new tab. If you are inside an iframe, you need to check the direction of the received message (upwards from inner iframe/downwards from parent window) by comparing the source of this event to the iframe content window. Finally, you need to resend the whole event to the parent window or inner iframe according to the event direction.

import { buildKontentLink } from '@kentico/kontent-smart-link';

function handleMessage(event) {
  const eventTypeRegex = /^kontent-smart-link:/;
  
  // check if this message is not related to the SDK
  if (!event.data || !event.data.type || !eventTypeRegex.test(event.data.type)) {
    return;
  }

  const isInsideIFrame = window.self !== window.parent;
  const message = event.data;

  if (isInsideIFrame) {
    // The iframe variable has a reference to the iframe element.
    // You don't have to use document.querySelector here, for example,
    // in React you can use `useRef` hook to save the reference and then 
    // use it here, in Vue you can use `$refs`, etc.
    const iframe = document.querySelector('#your-iframe-id');
    const isMessageGoingUpwards = event.source === iframe.contentWindow;

    if (isMessageGoingUpwards) {
      // resend this message to the parent window
      window.parent.postMessage(message, '*');
    } else {
      // resend this message to the iframe
      iframe.contentWindow.postMessage(message, '*');
    }
  } else if (message.type === 'kontent-smart-link:element:clicked') {
    const link = buildKontentLink(event.data.data);
    window.open(link, '_blank');
  }
}

Additional context

Add any other context, screenshots, or reference links about the feature request here.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions