Embedding Content in non-AEM experiences

In projects we often see the need to embed content in experiences that are not controlled by AEM. The need for that can arise from having an existing app or website that has been built using a web framework, an existing native app or simply the be a part of a migration where certain elements of a page (often the header with the navigation and the footer) need to be shared into legacy environments.

There are a number of different approaches to achieve this and we are trying to make it as easy and simple as possible for an existing application or site to consume content managed by AEM. One of the easiest ways to embed content for web and hybrid applications is to use Web Components which allows via a shadow DOM to isolate the CSS context completely from the containing environment.

This approach also allows to separate the development of design and functionality on the content side, and does not require updates or releases to the containing application in case there are changes to design, content or functionality of the embedded content and therefore has material advantages over a traditional headless development approach.

Using AEM Embed Web Component

As an application or website that needs to consume content from AEM it is as simple as adding the aem-embed web component to the project. Simply add javascript file to your project.

https://github.com/adobe/aem-embed/blob/main/scripts/aem-embed.js

…and include it with a <script> tag or load it as a module, depending what's easiest in your framework.

In a plain vanilla web project, it is as simple as adding one line to your <head> or anywhere else before the <aem-embed> tag is used.

<script src="/scripts/aem-embed.js" type="module"></script>

Once the aem-embed.js is added to your document you can just use the <aem-embed> tag to reference content from an AEM project via a url= attribute. This includes the referenced content similar to a fragment.

See usage examples here for a banner use case here:
https://main--aem-embed--adobe.aem.page/examples/banners.html

Since it is common to share a navigation managed by AEM in other experiences on a website there is special support for headers and footers via the type= attributes.

See usage examples for header and footer here:
https://main--aem-embed--adobe.aem.page/examples/header.html

Making your project embedable

CORS

Depending on the setup it might be necessary to change the CORS headers to allow access from all the consuming origins. An easy way to achieve that is to add a access-control-allow-origin header with the value of * via the headers in config service.

CSS & JavaScript

As web components change the DOM structure of a page, often CSS and JavaScript behavior need to be adjusted a little bit. Please find a list of common adjustments that need to be made to an existing project to be consumable.

If you are starting with a new project, it might be easy to just fork https://github.com/aemsites/embed-example

CSS :root

A lot of CSS uses :root especially to define CSS variables. For variables to work as expected adding :host to the CSS selector often is the only thing that's needed.

See commit for details

JavaScript loadPage() suppression

To make sure that the full page is not loaded in the case of an import happening via an aem-embed we need to suppress full page decoration in that case. This is usually done by replacing the loadPage() line in scripts.js with the following.

if (!window.hlx.suppressLoadPage) loadPage(document);

See commit for details

JavaScript header.js and footer.js changes

In cases you are planning to embed a header or footer there are potentially some changes to make sure that the header and footer can operate on content that is already in the DOM when they are called. Most header and footer implementations are responsible for loading their own content, and are not aware of content already being available in the DOM when the decoration step is started.

See examples for header and footer

JavaScript setting window.hlx.codeBasePath

If your site uses a site root path, you will likely need to adjust how this is set in aem.js.

See commit for details

Using the Embed Simulator chrome extension

To make it simple and easy to simulate what the end result on an embed looks like in an existing application or website without having to make any changes to existing application or site, there is a chrome extension available for use here.