Documentation

Learn how to build, publish, and launch your site with Adobe Experience Manager.

Resources

Bring Your Own Markup

Edge Delivery Services is independent of the authoring tooling and supports multiple content sources. This means you could provide your own content source and publish the content from a repository you already have to AEM without having to migrate the content first.

The API that enables it is called Bring Your Own Markup (BYOM). It uses HTML as the standard data format.

Bring Your Own Markup is widely adopted and two of Adobe's own content sources already implement it. BYOM is generic and easy to implement; it can be used for any content source.

What format should the source bring to the table

The data format for BYOM is HTML - in fact, it is the same semantic HTML structure used by Edge Delivery Services when rendering your website.

For each page that is previewed, your BYOM service must return an HTML response. This means that the HTML must follow the semantics of sections, blocks and default content.

A very minimal example of this looks like:

<!DOCTYPE html>
<html>
  <head>
    <title>Home</title>
  </head>
  <body>
    <header></header>
    <main>
      <div>
        <div class="hero">
          <div>
            <div>
              <p>
                <picture>
                  <img loading="lazy" alt="" src="myimage.jpg">
                </picture>
              </p>
              <h1>Hello World</h1>
            </div>
          </div>
        </div>
        <p>Welcome to your website.</p>
        <div class="metadata">
          <div>
            <div>
              <p>Description</p>
            </div>
            <div>
              <p>Page Description</p>
            </div>
          </div>
        </div>
      </div>
    </main>
    <footer></footer>
  </body>
</html>

Extra elements such as span tags, data attributes, or styles are removed when content is ingested. Page metadata can be provided via the common meta tags in the HTML head or via a metadata block with the page content.

Image source URLs within the content must be accessible by Edge Delivery Services. The images will be downloaded and ingested during the preview of the page. Image source can be an absolute URL or relative to the page.

Block class names

Block class names can only contain alphanumeric characters and single dashes and may not start with a digit. Underscores or double dashes are not supported. A block can have multiple classes. See also block options and block decoration.

What about sheets?

Structured data in the form of spreadsheets can be provided via BOYM as well. The data is provided as a JSON. The format of the JSON has to follow the Edge Delivery Services sheet format.

Setup BYOM as primary content source

The configuration of BYOM as the primary content source is carried out as for all projects either via fstab.yaml or via the configuration service..

A file based setup will use an fstab.yaml like this:

mountpoints:
  /:
    url: "https://content-service.acme.com/data"
    type: "markup"
    suffix: ".html"

If the site is set up using the configuration service the site config can be created like this:

curl -X POST https://admin.hlx.page/config/acme/sites/website.json \
  -H 'content-type: application/json' \
  -H 'x-auth-token: <your-auth-token>' \
  --data '{
  "version": 1,
  "code": {
    "owner": "acme",
    "repo": "website"
  },
  "content": {
    "source": {
      "url": "https://content-service.acme.com/data",
      "type": "markup",
      "suffix": ".html"
    }
  }
}'

The path of the page being published is appended to the provided BYOM source URL.

In both configuration options the "type": "markup" must be present to indicate this is a BYOM content source. "suffix": ".html" is an optional configuration, the admin service will add the suffix when requesting the content from the BYOM service URL.

How markup URLs are constructed

When a page is previewed with a BYOM markup source configured, the admin service constructs the request URL with the format {url.origin}{url.path}{contentPath}{suffix}{url.params}.

Where:

For example, given this BYOM configuration:

"source": {
  "url": "https://content-service.acme.com/data?foo=bar",
  "type": "markup",
  "suffix": ".html"
}

When previewing a page at /products/widget the constructed url will be https://content-service.acme.com/data/products/widget.html?foo=bar.

Setup BYOM as content overlay

BYOM can also be used as an overlay for another content source. It does not matter whether the primary content source is SharePoint, Google Drive or BYOM. However, the overlay content source must always be BYOM. A typical use case for such a setup is, for example, the automatic publishing of product pages directly from the commerce backend.

To use the content overlay the site must use the configuration service. A file based setup via fstab.yaml is not supported.

curl -X POST https://admin.hlx.page/config/acme/sites/website.json \
  -H 'content-type: application/json' \
  -H 'x-auth-token: <your-auth-token>' \
  --data '{
  "version": 1,
  "code": {
    "owner": "acme",
    "repo": "website"
  },
  "content": {
    "source": {
      "url": "https://acme.sharepoint.com/sites/aem/Shared%20Documents/website"
    },
    "overlay": {
      "url": "https://content-service.acme.com/data",
      "type": "markup"
    }
  }
}'

Lookup Order during Preview

If an overlay content source is configured, a preview request sent to the admin service will always result in the path being fetched from the overlay content source first. If the resource is not found in the overlay content source, the admin service fetches the path from the primary content source as a fallback.

Content Source Authorization

If the content source requires authentication, the preview request can include an x-content-source-authorization header. The admin service forwards this value to html2md, which then uses it as the Authorization header while fetching the markup from the content source URL.

x-content-source-authorization: Bearer <token>

Request Flow

  1. The client sends a preview request to the admin service with x-content-source-authorization: <value>.
  2. The admin service passes the value to html2md as part of the markup fetch request.
  3. html2md includes it as Authorization: <value> when retrieving the HTML from the configured content source URL.

This allows content sources that sit behind token-based or other HTTP authentication schemes to be used with BYOM without exposing credentials in the configuration.

Example:

curl -X POST https://admin.hlx.page/preview/acme/website/main/products/widget \
    -H 'x-content-source-authorization: Bearer eyJhbGciOiJSUzI1NiJ9...' \
    -H 'authorization: token <admin token>'

The value is forwarded verbatim — no transformation is applied — so it must be a valid Authorization header value accepted by the content source.

Error handling

If a protected overlay content source returns a 401 (missing credentials) or 403 (missing permissions) status code, the admin service treats it the same as a 404 (file not found) error and continues with a lookup of the path in the primary content source. As a result, a preview request could return a 404 from the primary content source, even if the resource to preview would be fetchable from the overlay content source, valid credentials provided.

Image Authentication for BYOM Content Sources

When Edge Delivery Services previews a page from a BYOM content source, it downloads and uploads all images referenced in the HTML to the media bus. If your content source requires authentication and your images are hosted on external domains that share the same credentials, the content source needs to tell Edge Delivery Services which image hosts are allowed to receive the authentication header.

How it works

By default, the authentication header used to fetch the source content is only forwarded to image URLs on the same host as the content source (self). Images hosted on other domains are fetched without authentication.

To allow the authentication header to be forwarded to additional hosts, the content source must include the x-html2md-img-src response header in its HTTP response. The value is a space-separated list of allowed origins, modeled after the img-src directive of the Content-Security-Policy header.

x-html2md-img-src: <source> [<source> ...]

The self origin is always implicitly included. This means images on the same host as the source URL always receive the authentication header, even if the header is absent or empty.

Supported source values

Value Description Example
* Wildcard. Forward the auth header to all image hosts. *
self The same host as the source URL. Always implicitly included. self
<host> An exact hostname. Auth is forwarded to images served from this host. images.example.com
*.<domain> Wildcard subdomain. Auth is forwarded to any subdomain of the domain. *.example.com

A full URL including protocol and path may be provided, but only the host portion is evaluated. The protocol and path are ignored.

Examples

Allow all image hosts to receive the authentication header

If all your images require the same credentials as the content source, use the wildcard:

x-html2md-img-src: *

Allow a specific CDN host

If your images are served from a dedicated CDN that shares credentials with the content source:

x-html2md-img-src: images.example.com

Allow all subdomains of a domain

x-html2md-img-src: *.example.com

Allow multiple hosts

Multiple sources can be combined in a single header value:

x-html2md-img-src: self https://images.example.com assets.cdn.net

No header or empty value

If the x-html2md-img-src header is absent or empty, only images on the same host as the content source will receive the authentication header. All other images are fetched without authentication.