Skip to content
Product Documentation

Technical Specifications for Custom Embeds (Power Up) in Composer

What is a Custom Embed?

Composer supports a method of integrating with foreign asset and content management systems called custom embeds. A custom embed is a way for developers to integrate portions of their own UI directly into Composer and return data for Composer to save in a story document.

To create a custom embed you need:

  • To be comfortable writing front-end UX code, including JavaScript
  • To host and serve the UX code reliably to iframes within Composer. This can be on your own server, or from a static environment, like Amazon S3.
  • To search and fetch content from your source system by id (for example, by making asynchronous HTTP calls)
  • (Recommended) To have an API endpoint that can serve rendering information about a piece of content on demand in an oEmbed-like way

Composer supports multiple types of custom embeds simultaneously, so you can build separate embeds with different types. For example, audio, videos, galleries, and images could each be a distinct type of embed.

Building the Admin UI

The admin UI of your custom embed consists of three panels:

  • Search Panel
  • View Panel
  • Edit Panel

Having all panels in place gives your authoring application the ability to use any third party media system including the ability to search for media, view it, and make any changes to it.

In Composer, you should first create a Custom Embed Type. Within that custom embed type, you can set a display name and a subtype value that distinguishes your custom embed type from the others.

You will also need to set a URL for each of the three panels listed above. For example, our reference implementation uses the following three URLs for its panels:

Search: https://d2o92lg4k51qh.cloudfront.net/audioSearchApi.html

View: https://d2o92lg4k51qh.cloudfront.net/audioViewApi.html

Edit: https://d2o92lg4k51qh.cloudfront.net/audioEditApi.Html

About the Panels

Search Panel

When a user adds your Custom Embed element to their document in Composer, your Search Panel appears. In this panel, the user can search, select, or sort content items from your foreign system and select one for adding to the document. For example, you might populate this iframe with a text box that lets users search for audio by title and then click OK to use it. The exact mechanism for finding and selecting content is up to you. You control the entire UI within the iframe.

Depending on which Custom Embed subtype you’re adding, you should use a corresponding search panel URL to load the search user experience. Search integration may receive any arbitrary data through the URL.

View Panel

Composer may need to display your Custom Embed type from the editor body, related content, or featured media panel. This panel is used to show your embedded content when a user is not interacting with it directly.

In order to do that, Composer creates an iframe and sets the iframe src attribute to the link to the preconfigured view panel URL. Composer makes any necessary substitution to the view panel URL from ANS to make a proper URL.

The View panel should not have Edit controls; however, it might contain some action buttons, such as play or stop. Composer loads the Edit Panel when a user initiates editing.

Edit Panel

This panel is available to allow users to edit the presentation of the selected foreign content within the context of the document. For example, on an embedded audio, a user might turn on autoplay and set a start position of 30 seconds. On an image, a user might set a caption or title.

This works similarly as the View Panel, except Composer waits for the submit or cancel message from the iframe. The submit message must have well-formed Custom Embed ANS in it with all the updates.

The Edit Panel may have a cancel button along with Submit button for the better UI. However, Composer may cancel editing at any time just by removing that iframe. No message will be sent to the Edit integration.

Unlike the View Panel, data returned from an Edit Panel requires a config object additionally to the required fields of url and id.

Iframe Communication Protocol Outline

The search, view and edit panels should each send a handshake postMessage to the parent window (window.parent.postMessage) as soon as they are loaded and ready to receive commands or interact with the user. If Composer does not receive the initial handshake message, Composer displays an error message with a Retry button.

The Search Panel is expected to return a configuration JSON on success search. Configuration JSON is subject to validation, see below.

The View Panel is expected to send only the handshake message. The View Panel receives configuration in the form of a query string (base64/encoded).

The Edit Panel receives configuration in the form of a query string (base64/encoded). The Edit Panel is expected to send the handshake message and the configuration JSON when a user submits changes. If user discards changes, a cancel message should be sent. Configuration JSON is subject to validation, see below.

Validation and Constraints

The final Custom Embed configuration has the following limitations:

  • Configuration should be a valid JSON.
  • JSON size should be no more than 2048 bytes length.
  • JSON should not have type, version, or referent fields at any level. Composer strips those out.

This JSON will be saved as a content element in the ANS document and is available for downstream consumers (for example, feature and template developers) to access.

Iframe Communication Protocol Specification

Composer communicates with the panels through query string data. Custom embed data is passed in as URL-encoded data in a p parameter in a form of JSON. Also, random key should be sent in a k parameter.

p - A Custom Embed data in a URL encoded JSON form
k - A random key to match the integration

Example:

Terminal window
editApi.html?k=d5ac90ec-096a-4cce-986a-b842f9d8d4c7&p=%7B%22id%22%3A%2217b3224337d2d3%22%2C%22url%22%3A%22https%3A%2F%

Plugins should respond back through the browser postMessage mechanism. Each message should be a JSON object and contain the following fields:

sourceAlways set to custom_embed
actionCan be only ready, data, or cancel
dataContains custom embed data or content height of the iframe
keyShould contain a value from the k query string argument

Ready Message

The ready message should be sent by each panel as soon as it renders their content and content height is known.

{
"source":"custom_embed",
"action":"ready",
"data":{"height":908},
"key":"d5ac90ec-096a-4cce-986a-b842f9d8d4c7"
}

If ready message will not be sent within ~10 seconds, Composer renders a timeout error and plugin content will be discarded.

Data Message

Data message should be sent by the Search Panel when an item has been selected by user and by the Edit Panel when editing is done. Data message should contain an ANS Custom Embed Data Structure. Feel free to check the Schema.

The data field is what will be persisted as a content element within the ANS document and available for front-end code to access when rendering the element.

{
"source": "custom_embed",
"action": "data",
"data":{
"id": "b0bc95dc11919",
"url": "https://my.content.com/data/2",
"config": {
"id": 2,
"text": "Some Text",
"image_id": 1
}
}
}

A data field should contain id, url and config fields. Those are required. Config object might have any arbitrary data structure. The only requirement is that it should not have referent, type and version fields. Config object should have as few fields as possible to properly configure the custom embed object.

Please do not put large objects here, as it becomes part of the url and is subject to the size limitations therein (2kb). Instead, use data.id to identify internal resource and data.config to store configuration properties only.

Cancel Message

Cancel message is used to notify Composer that user wants to cancel search or discard any editing changes.

{
"source": "custom_embed",
"action": "cancel",
"key":"d5ac90ec-096a-4cce-986a-b842f9d8d4c7"
}

The cancel message notifies Composer to close the UI. It does nothing for the view panel and should not be used there.

Composer can close search or edit the iframe by itself without notifying the iframe content. Please consider this behavior and do not persist any changes in the system. The only proper way to persist changes is to send data through data message back to Composer.

Message Communication Example

Composer Load a Search Integration

  1. Integration loads and sends back Ready message

    {
    "source": "custom_embed",
    "action": "ready",
    "data": {
    "height": 908
    },
    "key":"..."
    }
  2. User selects necessary media

    {
    "source": "custom_embed",
    "action": "data",
    "data": "something",
    "key": "..."
    }

Composer Load View Integration

viewApi.html?p=...

  1. View integration renders its content and sends back ready message with the content height.
{
"source": "custom_embed",
"action": "ready",
"data": {
"height": 480
},
"key": "..."
}

Composer Load Edit Integration

editApi.html?p=...

  1. Edit integration renders it’s content and sends back ready message with the content height.

    {
    "source": "custom_embed",
    "action": "ready",
    "data": {
    "height": 890
    },
    "key": "..."
    }
  2. User accepted changes

    {
    "source": "custom_embed",
    "action": "data",
    "data": {...},
    "key": "..."
    }
  3. OR User cancelled changes

    {
    "source": "custom_embed",
    "action": "cancel",
    "key": "..."
    }

Additional Resources