Search

Searching DEVELOPERS

Export Page

Content Authoring Developer Overview

This developer-centric technical overview of Content Authoring complements the more end user-centric Content Authoring Introduction that describes the content management problem along with the Amplience "Content Authoring" solution. Here we present in technical terms how our headless CMS provides the benefits associated with decoupled content management, and we outline the relationships between the Content Authoring components.

 Read about Decoupled Content Management...

Decoupled Content Management

The Amplience "Big Content Cloud" provides a headless Content Management System (CMS), which means that the presentation of content (e.g. as HTML web pages) is decoupled from the content structure in the CMS.

Most CMS systems present three major challenges:

  1. They focus on managing your website rather than your content.
  2. They monopolize the presentation layer, making cross-platform publishing and custom user experiences difficult to create and manage.
  3. It is difficult to add new channels such as mobile apps and microsites without duplicating your content.

Our presentation- and platform-agnostic solution aims to solve these problems by decoupling our back-end content storage and management (the Content Authoring CMS) from your front-end multi-channel presentation. The Content Authoring tool facilitates the storing, editing and publishing of content, but also addresses a number of content management problems such as content reuse and responsive design.

The benefits of a headless CMS include:

  • Giving front-end specialists full control over the user experience using native tools.
  • Shifting display logic to client side while the server-side CMS concentrates on delivering content.
  • The ability to create once and publish everywhere.
  • Organization and structure of content in a logical way that is not restricted by fixed predefined templates.
  • A relatively non-technical user interface.

With Content Authoring you can:

  • Describe your content types using the JSON Schema open standard, which defines the content and structure that your presentation layer needs to capture.
  • Use tools that provide user-friendly interfaces for populating those content type schemas with content.
  • Deliver content to your presentation layer in a platform-agnostic way using REST APIs that deliver standard formats including JSON, JSON-LD and Markdown.
  • Devise front-ends (rendering kits) that turn the platform-independent content into HTML web pages, native user interfaces, and more.
  • Utilize Dynamic Imaging to deliver the right size and quality images for different devices and screen sizes.

The decoupled content management is illustrated by the following diagram, in which the dashed line indicates point at which the front-end "head" is decoupled from the back-end CMS (thus making it headless).

 See the Content Authoring Components...

Content Authoring Components

The following diagram shows the Content Authoring components, their relationships and interactions. In short, Your App calls the API which fetches Content that is based on Content Type Schemas.

Note that Content Authoring uses the concept of content "cards" (bottom-right of the picture) that provide visual representations of the content for easy identification by content authors. These cards are not necessarily representative of how the content will look when delivered by your application to different devices (desktop, tablet or mobile phone) with different screen sizes; they are merely a visual aid for navigating content. There are many built-in cards, and you can also build your own.

Content Authoring Development Concepts

Here we explain the key concepts that underpin the use of Content Authoring from the perspective of the software developer.

 Read about the "Data Modelling" concept...

Content Authoring Concepts - Data Modelling

One of the first steps when using Content Authoring is to define the content data you wish to store. This process usually involves breaking down specifications, wireframes and designs into components that can be implemented using primitive data types. These components are encoded as JSON schemas which define the content type templates that will be to content creators as screen forms.

Let's take a very simple example of a carousel shown schematically as a wireframe here:

The wireframe above comprises:

  • A title.
  • Image content.
  • Navigation arrows.
  • Slide selector dots.

When modelling the data for this wireframe, we make the following assumptions:

  • The title applies across all slides, not unique to each slide.
  • Each slide contains only an image.
  • The navigation arrows and screen selectors are user interface properties that do not require any specific content.

In the table below, you can see our example data model that defines a title string plus multiple slides in an array.

FieldTypeValidationAcceptance Criteria
carouselTitleString
  • Mandatory
  • Maximum of 255 characters.
  • Content is entered in plain text format.
  • Schema will not save without a title.
  • Use can enter alpha, numeric and special characters.
carouselSlidesArray
  • Mandatory
  • Minimum of 1 slide.
  • Maximum of 5 slides.
  • Slides can be re-used.
  • Slides must be imaged from the Amplience Dynamic Media platform.
  • Slides can be re-ordered.
  • Slides can be removed.

The JSON schema that implements the data model, and which includes appropriate validation (see Content Authoring - Schema Validation), is given here:

 See the JSON Schema code...

The content type form that is generated for this schema in the Content Authoring app is as shown below. Note the correspondence between the form fields and the original modelled data fields.

In the example screen shown above, the content editor user has populated the content type form with a title and a number of images. When published, the JSON-LD response for this content is as follows.

The URL for this content response, which would be used to retrieve the content into a front-end application via the Delivery API is https://c1.adis.ws/cms/content/query?fullBodyObject=true&query=%7B%22sys.iri%22%3A%22http%3A%2F%2Fcontent.cms.amplience.com%2Fa276f425-8802-4f99-a6a4-96ba18cc1ba4%22%7D&scope=tree&store=playground

 Read about the "Schema Relationships" concept...

Content Authoring Concepts - Schema Relationships

There are two methods for combining content:

  • Nested / Linked content, whereby the linked item is independent and may be shared by a number of assets that all link to it.
  • Inline content, which forms part of the whole and is indivisible from it, thereby providing reuse of structure but no reuse of content. 

Nested / Linked Content allows the user to create and add other content types to an existing content item; for example the user may wish to compile a carousel made up of several different image slides. This approach to linking otherwise independent content allows for re-use, by making the linked content available via the Content Browser as an independent item. One effect of this is that an update to the linked content will be reflected in all the content that links to it; e.g. all carousels that show a particular image slide will change if the image slide is updated. In technical terms, this is like linking objects "by reference" in an association arrangement.

Inline Content works by embedding one content type within another one by (the developer) embedding one schema within another one, which in technical terms is like linking the objects "by value" in an aggregation / composition arrangement. It is applicable to simple compositions where a particular set of fields and validation are required for inclusion in a particular content type but without the values being shared across multiple content objects. 

Analogies

Web pages tend to be linked into many other web pages, hence the content contained within a particular page (which exists in its own right) may be shared or re-used across other pages. This is nested or linked content. 

In contrast, the chapters of a novel are unique to that particular novel. So while the definition of a chapter (as a thing with a title and a number of prose paragraphs) may be reused across all novels and even non-fiction books (because they all have chapters), no two books contain the same chapters.

Content Authoring Concrete Examples

Theory is all well and good, but the distinction is best illustrated with a couple of concrete examples in the context of Content Authoring.

Nested / Linked Content

The Product Article content type allows you to include one or more existing Articles as shown in the following picture. These Articles are independent of the Product Article into which they are being included, and the content editor includes them by browsing for them using the Content Browser. Any Article may be nested into / linked to more than one Product Article.

Inline Content

Various content types including carousel slides and images may require the exact same standardised "call to action" with a fixed number of fields (Image Url , Call to Action Label, Call to Action Url) and associated validation as shown below, but with distinctly different values in each case. So the same structure may be reused across several schemas, but not the content entered into that common structure.

Inline content never exists in its own right independent of the containing content, and hence cannot be reused via the Content Browser of the Content Authoring application.

When to Use Each Kind of Included Content

When deciding between nested content and inline content, the things you should consider include:

Granularity: Do you merely want to break down a big unwieldy schema into smaller parts for clarity, and to factor out potentially reusable definitions? This would be inlining.

Reuse: Do you also want the content items defined by these sub-schemas to be shared among multiple content items? This would be nesting or linking.

Ownership / Lifetime: Do the items defined by the sub-schemas somehow "belong" to the containing schema, such that they should cease to exist at the same time? This would be inlining.

In context of the Content Authoring workflow, it is the developer who determines what schema structures get reused through inlining whereas it is the content editor who decides what content gets reused via nesting / linking.

 Read about the "Validation" concept...

Content Authoring Concepts - Validation

Validation can be applied to schema attributes. These validations allow the data model to be constrained to contain information only in formats that renderers can understand. Enforcing the data model through validation can reduce the need for testing by ensuring the safety of content for front-end display.

Some validation examples are:

  • Maximum number of characters for a title in a schema.
  • The maximum number of slides allowed in a carousel.
  • A schema must have at least one image.
  • A field must be in a URL format.

Validation rules can be applied individually or as combinations to ensure that the content is consistent for the end consumer.

Besides constraining the data that can be entered into content fields, validation can also serve to provide the user with feedback in the form of textual hints like this:

The result in this case would look like this:

Validation constructs adhere to JSON-Schema validation: http://json-schema.org/latest/json-schema-validation.html, and more information is available in the reference section Content Authoring - Schema Validation.

 Read more about the "Consuming Content" concept...

Content Authoring Concepts - Consuming Content

The whole point of a headless CMS is to serve up content to front-end applications, web sites, and other clients in a presentation-independent way. The implication therefore, is that there must be a way (or ways) for client applications to retrieve content from the Amplience CMS. In this context, we provide:

  • An Application Programming Interface (API)
  • A Software Development Kit (SDK)
  • A content previewing capability based on the concept of "cards".

The API

In simple terms, the Content Delivery API is accessed by formulating a URL of the form shown below, where the highlighted characters are the unique asset ID of the content to be retrieved.

The result takes the form of a JSON-LD graph (shown below) that must be flattened for rendering by the front-end application.

The SDK

The SDK provides an inlineContent() method that can be used to "inline" the JSON-LD response data retrieved via the API. Some sample code to output the inlined response data to the web browser log window would look like this:

// Use the SDK to inline the content from the graphs.
 var inlineResult = amp.inlineContent(data);

// This is the new content
console.log("This is the result inlined:");
console.log(JSON.stringify(inlineResult));
console.log("---");

if(inlineResult && inlineResult.length === 1){
// Now log out the text from the inline content
console.log("The text is here:");
console.log(inlineResult[0].text);
console.log("---");

The Content Cards

Our own Content Authoring app uses the concept of "cards" to provide sample representations published and not-yet-published content in the Content Library. While not representative of how content will or should be displayed by front-end applications, we do make these cards available to other systems that may wish to provide preview representations of content. For example, you may wish to incorporate out content previews into you existing CMS business tooling.

Each content type schema defines the card that should be used to preview its content, plus the mapping between the schema fields and the card fields:

As shown schematically here, a card template HTML page (in this case for the "gallery" card) can be used to display the content retrieved from the CMS Administration API:

Note that unlike the Delivery API that provides unauthenticated access to published content, the Admin API that returns unpublished content to be previewed in cards is authenticated. It is beyond the scope of this section to detail this second API and its authentication.

The end result is a card that provides a rendering of the content. Here is a selection of built-in cards that render content in different ways:

Further Reading

More information about consuming content can be found in Content Authoring - Delivery API and SDK and Content Authoring - Development Demonstrations.

 

 Read more about the "Updating Content Types" concept...

Content Authoring Concepts - Updating Content Types

There will be occasions during a project lifecycle where content types will need to be updated. These could be simple alterations such as a new icon or some better hints in the UI for the business user, but can also be more intrinsic changes to the data model. Below are some example use cases and impacts.

Overall risk

Updating a content type is like updating the structure and attributes in a database table. Minor changes can have no impact but certain changes can lead to data (content) loss without appropriate backups and migration.

Overall Recommendations

The points below may seem fairly generic and applicable to all implementations, but they are also valuable for Amplience content authoring.

1: Specify first

Creating content types can be extremely easy in Amplience so there is often an urge to skip the specification stage. This can be great, but it is easier to deal with change if there is a specification so that impacts and dependencies can be known up front. This will also speed up content type development time as the stories and expectations will be better known and suitable to test.

2: Test early - Fail fast - better results.

At the start of a project, always populate content with low value, throw away dummy content. This allows all parties to approve the content type structures and the end result / display of the content. Changes can be made with minimal risk.

3: Phase content production

Following dummy content, produce a few real examples of content use for stakeholder approval. Generally, this will require fewer content type changes but will provide better testing for front end renders.

4: Validate where necessary

Validation is a great feature to ensure that content created can fit in bounds of the rendering templates on the front end application. They assists with the NFR's for development too. It is not always necessary to validate all fields as certain content (such as paragraph text) can flow depending on the size of the article.

5: Backup

Always create a backup before making any changes to content types.

6: Versions

If in doubt, it is best to take a copy of your existing content type and create a new version with the changes. For example "My Content Type" could remain as is, and new content could be created with a content type called "My Content Type V2"

Scenarios:

Changing content type meta data.

The content type meta data contains information such as:

  • Name
  • Description
  • Icon
  • Card
  • Visualisation(s)

These are all internal Amplience attributes and can be changed at any time without affecting the content itself.

Changing a property name

A content type is made up of a series of properties. These properties are effectively the fields in the database where the content is stored.

This is also the name of the property in the CMS API and is how front end code knows what to render.

Changing a property name will result in:

  • Previously populated content for the modified field being removed from all instances of that content type
  • Published content will continue to use the old name until re-published ( either by itself or as a dependency for another publish ).
  • User will need to re-visit the content instance and add the attribute for that field again and re-publish.

Changing a property label

Changing any of the property label attributes will affect the front end form which the business users see when creating content, but will not change the structure of the published content.

Adding a new property

Adding a new property to your content type will not affect any existing content. Please note that any front end code will need to be updated in order to show your new property.

Removing a property

The property will no longer be visible to the content editor but existing published content will continue to serve the old field until re-published (either by itself or as a dependency for another publish).

Changing a property type

This carries the largest risk. Changing data types can lead to corruption of data and corruption of the form itself. Generally instead of changing a data type it would be recommended to add a new field with a new data type.

Changing Validation on a property

Changing the validation on a property will not remove the existing content if it is invalid, it will still remain. In fact even if you re-edit the content, the legacy content will remain and be classed as valid UNLESS you edit the property itself. If you edit the property itself, the latest content must adhere to the validation otherwise the content will not save.

 

Content Authoring Development Demonstrations

Here we provide a series of end-to-end development demonstrations that that go all the way from content creation to consumption. The demonstrations follow a logical sequence with each one building on the one that went before, so it makes most sense to work through them in order.

Prior to working through these development scenarios (or "developer use cases") you might want to familiarize yourself with the Content Authoring workflow and the quick-start steps.

 See the "Simple Text" Development Demonstration...

Content Authoring "Simple Text" Development Demonstration

This first scenario demonstrates the creation and consumption of simple text content. 

Step 1: Create the "Hello World" Simple Text Schema

The "Hello World" JSON schema (hello-world.json) provided below contains a single text field named "text" which has a limit of 256 characters. For the purposes of this demonstration you can simply copy this code into the Content Authoring application's Schema Editor as described in Step 1 of the Content Authoring Quick Start.

 See the hello-world.json schema code...

 

 

 

 Save the Schema as a content type named "Hello World".

Step 2: Create the Content in the Content Type Form

Each developer-created JSON schema is reflected as a content type in the Content Authoring application. You can click the "Hello World" content type icon to launch the Content Type Form:

Once the required text content has been added and saved, and the content has been published as described in Step 3 of the Content Authoring Quick Start, you can obtain the Asset ID and JSON URL for the resulting content asset as shown next. This will be used subsequently to consume the content via the Delivery API.

In this case the Asset ID is C76EAC2B-8FC9-47F3-BD6F-193C64400A8F. The JSON URL can be can be deduced by clicking the link labelled "View Live Delivery URL" and then copying the URL from the browser window that appears:

In our case the URL to be provided to the Delivery API as follows (but yours will be different):

https://c1.adis.ws/cms/content/query?fullBodyObject=true&query=%7B%22sys.iri%22%3A%22http%3A%2F%2Fcontent.cms.amplience.com%2Fc76eac2b-8fc9-47f3-bd6f-193c64400a8f%22%7D&scope=tree&store=playground

Step 3: Consume the Content

Now we build a simple web application to consume the content.

Step 3.1: Logging Out the "Hello Word" Text with AJAX and jQuery

The example page at http://c1.adis.ws/c/playground/step-001_-_hello-world-log does the following:

  • Gets data using AJAX & jQuery.
  • Logs out data.
  • Finds result and graph ID.
  • Finds graph item with matching ID.
  • Logs out the "Hello World!" text content using console.log.

You can see the result by inspecting the web page and viewing the Console as shown here:

The underlying code can be viewed by using the "View page source" option to reveal:

Step 3.2: Logging Out the "Hello World" Text with the SDK

The example page at http://c1.adis.ws/c/playground/step-002_-_hello-world-sdk-log does the same thing, but using the Amplience CMS SDK. The code in this case is:

Step 3.3: Building Some Basic HTML

In the real world we would not be logging out the results, we'd be presenting them on a web page. So on the next example web page at http://c1.adis.ws/c/playground/step-003_-_hello-world-sdk-html-edit we build some basic HTML. The code, which now writes the text to a DIV on the page, looks like this:

And the result is:

Step 3.4: Replacing Manual HTML Manipulation with a Handlebars Template

Rather than relying on manual HTML manipulation, we use a Handlebars template in the example at http://c1.adis.ws/c/playground/step-004_-_hello-world-sdk-html-edit-template. The result is pretty much the same as the previous picture, but in this case the HTML code underlying the web page is:

Step 3.5: Add Some Style

In the final step, demonstrated at http://c1.adis.ws/c/playground/step-005_-_hello-world-sdk-html-edit-styled-template, we apply some simple styling:

The additional styling code enclosed within the <style> tag looks like this:

 See the "Simple Text and Image" Development Demonstration...

Content Authoring "Simple Text and Image" Development Demonstration

This use case extends the Simple Text scenario to include an image.

Include an Image Definition in the Simple Text Schema

The simple text schema now contains an image definition within the "definitions" section of the schema. An image must validate as a "di-asset-link" and must be of semantic type "asset".

Create and Consume the Content

Via the Content Authoring app we can add an image to the content type that represents the schema we just created:

Then we publish the content:

In this case the details are:

Asset ID:

A3CB5CD4-14E3-42E2-A3B9-2C7709C2F48C

URL:

https://c1.adis.ws/cms/content/query?query=%7B%22sys.iri%22%3A%22http%3A%2F%2Fcontent.cms.amplience.com%2Fa3cb5cd4-14e3-42e2-a3b9-2c7709c2f48c%22%7D&scope=tree&store=playground&fullBodyObject=true

Here you can see the image included in the API response:

Consume the Content

Having constructed the schema and populated it with content, we can now consume the content.

Step 1: Construct the Image Retrieval URL

The "graph" section of the response (shown above) contains fields for the image that identify its defaultHost (i1.adis.ws), endpoint (playground) and name (womanwall). Taken together, these allow us to construct the following URL to retrieve the image:

http://i1.adis.ws/i/playground/womanwall

We can even append some Dynamic Media parameters to manipulate the returned image on-the-fly:

http://i1.adis.ws/i/playground/womanwall?w=300&qlt=50&unsharp=0,1,1,7&fliph=true

The end result looks like this:

Step 2: Update the Rendering Template to Include the Image

Although the image is included in the API response, it does not yet render alongside the "Hello World!" text on the example page at http://c1.adis.ws/c/playground/step-006_-_hello-world-change-content (see below) because the image is not yet in the template.

Here is the modified Handlebars template to include the image, which utilises the image.defaultHostimage.endpoint and image.name from the API response in order to compose the image URL.

 

The result at http://c1.adis.ws/c/playground/step-007_-_hello-world-image now looks like this:

Step 3: Restyle the Image and the Text

In the previous step the image is too big, and the end result would look much better like this:

So the final example at http://c1.adis.ws/c/playground/step-008_-_hello-world-image-styled contains code to restyle the image and the text:

 See the "Responsive Imaging" Development Demonstration...

Content Authoring "Responsive Imaging" Development Demonstration

In the "Simple Text and Image" use case we created a schema that contains image content references, and we used Dynamic Media parameters to manipulate images on-the-fly. In this use case we go further by utilising Dynamic Imaging to deliver "responsive" or "adaptive" images that adjust to the size of the device screen or web browser window.

Please Note: While the following examples expose and code the dynamic imaging parameters directly in the image URL for simplicity and clarity, for best practice we would recommend putting these transformation parameters into Transformation Templates (TT's). You can find more details about this herehere and here.

The current image tag, which loads a single fixed-size image into the page, is:

<img src="https://{{image.defaultHost}}/i/{{image.endpoint}}/{{image.name}}?w=400">

A couple of concrete examples using the Dynamic Imaging service are:

Step 1: Use the SRCSET Attribute

In this example, we'll re-use the existing image tag template and update it to use the SRCSET attribute to define different image sizes for different screen widths. Specifically, we will:

  • Load a 500px wide image if the screen is 500px wide.
  • Load a 1000px wide image if the screen is 1000px wide.
  • Load a 2000px wide image if the screen is 2000px wide.
  • Default to a 400px wide image if the web browser does not support the SRCSET attribute.

We make coding these tags simple by defining image transformations directly in the URL, and by supporting template systems such as Handlebars for re-use. The code is:

<img src="https://{{image.defaultHost}}/i/{{image.endpoint}}/{{image.name}}?w=400" srcset="https://{{image.defaultHost}}/i/{{image.endpoint}}/{{image.name}}?w=500 500w, https://{{image.defaultHost}}/i/{{image.endpoint}}/{{image.name}}?w=1000 1000w, https://{{image.defaultHost}}/i/{{image.endpoint}}/{{image.name}}?w=2000 2000w">

Note that in our examples, the image reference is always the same. Only the parameters change, to transform the image to match the SRCSET rules.

The example web page at http://c1.adis.ws/c/playground/step-009_-_hello-world-image-srcset can be resized (as shown below) to see how the image adapts accordingly.

Step 2: Incorporate the Picture Element

The picture element allows us to set up different sources of media for different breakpoints, for example for the image to adjust at certain boundaries (320w, 768w, 1024w, 1440w, 1920w, 2560w) rather than adjusting continuously as the size of the browser window changes. Each source can then have its own SRCSET of media, with the SRCSET controlling the pixel density (e.g. 1x or 2x). 

The unique code for this example is:

 

The complete code for this example can be found in the page source at http://c1.adis.ws/c/playground/step-010_-_hello-world-image-picture. Launch the page and resize the browser window to see how the image size changes only at discrete size boundaries.

Step 2.1: Image dimensions

Towards the bottom of the previous code sample, you will see some extra parameters assigned to the lower resolution media:

sm=aspect&aspect=1:1

These parameters will crop the media to ensure that the response has a 1:1 aspect ratio that crops by default around the centre of the image. Here are some alternative aspect ratio examples that illustrate what difference it makes:

Example original: https://i1.adis.ws/i/playground/womanwall?w=500

Example at 1:1 aspect: https://i1.adis.ws/i/playground/womanwall?w=500&sm=aspect&aspect=1:1

Example at 4:3 aspect: https://i1.adis.ws/i/playground/womanwall?w=500&sm=aspect&aspect=4:3

Example at 1:2 aspect: https://i1.adis.ws/i/playground/womanwall?w=500&sm=aspect&aspect=1:2

Step 3: Using Point of Interest

The problem with cropping around the centre of the image is that this may not be where the "action" is; i.e. not what the viewer really wants to see in the image. Consider the following 1:2 aspect ratio example (w=500&sm=aspect&aspect=1:2) that leaves the model lady out of the shot.

This is where a "point of interest" comes in useful as our way of ensuring that an image is cropped around the most interesting part of an image. The Amplience "Point of Interest" app allows us to assign a point of interest on an image as shown here:

This point of interest information is retrievable as metadata, which we can use in commands to ensure that the image always crops around the required point rather than around the centre:

w=500&sm=aspect&aspect=1:1&scaleFit=poi&poi={$this.metadata.pointOfInterest.x},{$this.metadata.pointOfInterest.y},{$this.metadata.pointOfInterest.w},{$this.metadata.pointOfInterest.h}

POI example images can be viewed at the following URLs for the 1:1 and 1:2 aspect ratios respectively:

https://i1.adis.ws/i/playground/womanwall?w=500&sm=aspect&aspect=1:1&scaleFit=poi&poi={$this.metadata.pointOfInterest.x},{$this.metadata.pointOfInterest.y},{$this.metadata.pointOfInterest.w},{$this.metadata.pointOfInterest.h}

https://i1.adis.ws/i/playground/womanwall?w=500&sm=aspect&aspect=1:2&scaleFit=poi&poi={$this.metadata.pointOfInterest.x},{$this.metadata.pointOfInterest.y},{$this.metadata.pointOfInterest.w},{$this.metadata.pointOfInterest.h}

In both cases, the model is always in-shot:

The final example using a point of interest image can be found at http://c1.adis.ws/c/playground/step-011_-_hello-world-image-poi.

Step 4: Adapting for SEO

We can apply some simple additions to images that will help with search engine optimisation. The following examples all use the same textual content.

Add an "alt" and "title" Attributes to the Image
Use the "figure" and "figcaption" Elements

Use the 'Apparent Filename' Functionality

We can also use the Amplience apparent filename / SEO filename functionality as described in the SEO section at http://playground.amplience.com/di/app/#/integration.

Taking the original image request of https://i1.adis.ws/i/playground/womanwall, we can apply an apparent filename to give https://i1.adis.ws/i/playground/womanwall/this-is-my-filename.jpg.

Next we can apply transformation parameters to give https://i1.adis.ws/i/playground/womanwall/this-is-my-filename.jpg?w=500&sm=aspect&aspect=1:1&scaleFit=poi&poi={$this.metadata.pointOfInterest.x},{$this.metadata.pointOfInterest.y},{$this.metadata.pointOfInterest.w},{$this.metadata.pointOfInterest.h}

Before using this in our template, we must make sure that there are no special characters or spaces in the filename for the image. The following code adds a new attribute named "seotext" to the data from the service, which has any special characters replaced with '-' hyphens.

Then we can use this attribute or property when generating image URLs. Look out for "seotext" in this code:

The final example web page for this use case can be found at http://c1.adis.ws/c/playground/step-012_-_hello-world-image-seo

Further Reading

Additional "point of interest" documentation can be found at http://hub.amplience.com/display/USERS/Point+of+Interest+(POI)+user+documentation and http://playground.amplience.com/di/app/#/advanced.

Additional information about the Dynamic Media platform can be found at http://playground.amplience.com/di/app/#/intro and http://hub.amplience.com/display/USERS/Dynamic+Media.

 See the "Validation" Development Demonstration...

Content Authoring "Validation" Development Demonstration

The purpose of validation in schemas is to ensure that entered data is in a correct format. In this use case we extend the original "Hello World" image schema to include validation. An extract from the new schema (hello-world-image-validation.json) is shown below, and we will refer back to it.

This schema defines two properties or fields, one for text and the other for an image, and we will step through the validation for each of these in turn.

Step 1: Text Validation

The first thing to note about the text field is that it is mandatory, hence this code at the foot of the schema definitions shown above:

"required": ["text","image"]

This also defines the image field as being mandatory, but we're getting ahead of ourselves.

As well as being mandatory, we specify that any user-entered text must begin with a capital letter and must be between 5 and 50 characters in length. We do this using the "minLength", "maxLength" and "pattern" attributes:

The result of this validation can be seen when a content editor user tries to enter incompatible information into the fields of the content type form for this schema. First the UI displays an asterisk next to the "Text" field to denote it as mandatory (1); then it displays an error message when the user tries to save the form without entering any text (2):

Next, the UI responds appropriately with error messages when the user tries to enter text that breaks the validation rules:

Step 2: Image Validation

We also need to define the image object as being compliant with the di-asset-link schema, as being of mediaType "image", and as being of semanticType "asset":

We showed earlier how the image (as well as the text) could be defined as being mandatory:

"required": ["text","image"]

This results in the image place-holder being annotated with an asterisk in the UI. It also triggers the display of an error message if the user attempts to save the content type form without specifying an image:

Complete Schema Code

 See the complete code for this schema that includes validation...

 See the "Relationships" Development Demonstration...

Content Authoring "Relationships" Development Demonstration

As with any type of software coding, schema coding can benefit greatly from modularisation. There are two ways to link sub-schemas to a containing schema: Content Linking (aka Nested Schemas), and Inlining.

In this example, we would like to create a new schema that can contain multiple existing "Hello World" schemas, but without pasting the same sub-schema code into the containing schema multiple times.

 See the "Hello World" schema code (which will be our included sub-schema)...
 See the content linking / nesting approach...

Content Linking

In this case, the Hello World schema will be linked to the containing schema such that any container content instance will contain one or more independently-existing "Hello World" content instances. 

Below is the framework for the containing schema. As well as defining a "headline" within the set of definitions, it also defines a number of content items as asset links within an array. Each of these links must validate against the "Hello World" schema that is referenced by its Schema ID. 

Step 2: Create the "Hello World" Content Items

First we create some "Hello World" content items that have their own independent existences outside of the container.

Step 3: Create the Container Content

Next we create the content for the containing schema, which has a "headline" at the container level plus place-holders for the "contained" content items.

Step 4: Add a Linked Content Item

Now we can proceed to add a content item of the "Hello Validation" content type (next three pictures).

Step 5: Add (and Create) More Linked Content Items

Because we defined an array list of contained items in the containing schema, we can add a second linked item:

We can even create an entirely new one to be linked (next two pictures):

Step 6: Save, Publish and View

Now we publish the container content, and get its link...

...so that we can build the example page rendering at http://c1.adis.ws/c/playground/step-013_-_hello-world-container. On this page you can view the linked content items rendered in sequence, and you can view the page source to see how we did it.

 See the inlining approach...

Inlining Content

Alternatively it is possible to use inlining in those cases where you wish to reuse schema definitions that exist in a separate schema, but not reuse content that exists independently.

Step 1: Create the Containing Schema with the Inline Schema Referenced

In the inlining case, the JSON code for the containing schema looks like this:

In this case, the code to include one or more array items of the included schema is:

"$ref": "http://schema.cms.amplience.com/{{hello-world-schema.id}}"

Notice the much simplified "items" section, with no necessity to use the allOf validation for the array type(s). But we do need to include the "interpolate": true flag so that the Content Authoring UI knows that this is an inline rather than a nested / linked schema.

"_interpolate": true

And we include the following label code to override the label that was defined at the "Hello World" sub-schema level, so that it makes more sense when adding content items of the sub-schema type. 

"value": "Hello World Image",
"hint": "Hello World schema to show a textual example with an image and validation"

Step 2: Create the Content

When adding content for this container schema (and sub-schema), the content type form looks like this:

Notice how the entire set of fields for the inlined content (in this case "Text" and "Image") are available for editing right on the container form... but shown visually as embedded within an outline box. Because the containing schema's array definition allows more than one item, we can click the "ADD HELLO WORLD IMAGE" link to add another Text+Image "Hello World" combo. This is what it looks like with two items added:

Step 3: Save, Publish and Consume the Content

Once the content is published and saved in the usual way, it can be consumed by a front-end application.

An example request for the content would be: https://c1.adis.ws/cms/content/query?fullBodyObject=true&query=%7B%22sys.iri%22%3A%22http%3A%2F%2Fcontent.cms.amplience.com%2Fffd734d0-8ac1-4c78-a037-e06ae53b8846%22%7D&scope=tree&store=playground

The response would look like this:

Although the response structure differs in the cases of linked and inlined content, our JavaScript SDK inlineContent() method makes the content suitable for rendering using exactly the same rendering template in both cases.

An example page showing the end result can be found at http://c1.adis.ws/c/playground/step-013a_-_hello-world-container-inline

 See the "Reusing Data" Development Demonstration...

Content Authoring "Reusing Data" Development Demonstration

In this use case we retrieve exactly the same content as with the previous Relationships example, and present it in different ways. In the page sources for both of the examples demonstrated below, you will find the same asset ID 7f0e2816-d25e-4a44-8569-6f8b05321de3 for the retrieved content. We are therefore demonstrating the decoupling of content and presentation.

Data Displayed using Masonry

The web page at http://c1.adis.ws/c/playground/step-014_-_hello-world-container-masonry uses the Masonry JavaScript grid layout library to display the content. It looks like this:

Same Data Used on a Carousel Page

The web page at http://c1.adis.ws/c/playground/step-015_-_hello-world-container-carousel presents the exact same content in the form of a carousel.

 See the "Content Authoring - "Simple Video" Developer Demonstration...

Content Authoring "Simple Video" Development Demonstration

This use case shows an example consuming Amplience Video in a HTML5 video tag. The end result can be seen here: http://c1.adis.ws/c/playground/step-016_-_hello-world-video.

Step 1: Create a Simple Video Schema

The simple video schema contains a video title and a video. A video must validate as a "di-asset-link" and must be of semantic type "asset".

Create and Consume the Content

Via the Content Authoring app we can add a video to the content type that represents the schema we just created:

Then we publish the content:

In this case the details are:

Asset ID:

e7f54aa9-386b-49bb-9d76-b72a188a8da2

URL:

https://c1.adis.ws/cms/content/query?fullBodyObject=true&query=%7B%22sys.iri%22%3A%22http%3A%2F%2Fcontent.cms.amplience.com%2Fe7f54aa9-386b-49bb-9d76-b72a188a8da2%22%7D&scope=tree&store=playground

Here you can see the video included in the API response:

Consume the Content

Having constructed the schema and populated it with content, we can now consume the content.

Step 1: Construct the Video Retrieval URL

The "graph" section of the response (shown above) contains fields for the image that identify its defaultHost (i1.adis.ws), endpoint (playground) and name (AnyaFinn-Shoppable). Taken together, these allow us to construct the following URL to retrieve the video. 

http://i1.adis.ws/v/playground/AnyaFinn-Shoppable

Calling the video directly will give you the thumbnail image assigned to that video - we can add commands to size the image as appropriate:

http://i1.adis.ws/v/playground/AnyaFinn-Shoppable?w=1280

The end result looks like this:

Step 2: Loading video information

We now need to retrieve video information from the video meta data api, so that we know the details of the video transcodes available for consumption. Useful reference links:

Playground for Amplience video: http://playground.amplience.com/di/app/#/video

Video API: http://hub.amplience.com/display/USERS/Video+Transcoding+API

To do this, we will request the video as JSON:

https://i1.adis.ws/v/playground/AnyaFinn-Shoppable.json

You can see the API response below:

The example loads this as a simple AJAX request using the information from the CMS API:

 

Step 3: Sorting available videos (optional)

In this example, we will be sorting the available videos from the video meta data API in order of quality ( highest first ). To do this, we have created a simple helper function to transform the data and return in the correct order.

We can call this sending in the video meta data in order for it to be transformed:

Step 4: Add the video meta data to the CMS data

In this example, we are combining the data from the 2 API's so that can use a single handlebars template to produce the HTML output.

Step 5: Create a simple video Rendering Template

This template will display:

  • Video Title
  • Video tag with poster image
  • Video sources in order of quality.

Template is below:

Notice that this template uses a helper called "getVideoFormat". This ensures that the video sources have the right attributes to describe the video to the browser in the right format. This helper is listed below and accepts an individual transcoded video from the API:

Step 6: See the result

URL: http://c1.adis.ws/c/playground/step-016_-_hello-world-video.

 

 See the "Content Authoring - "Simple Video - VideoJS" Developer Demonstration...

Content Authoring "Simple Video - Video JS" Development Demonstration

This use case builds on the previous Content Authoring - "Simple Video" Developer Demonstration and uses the same schema. It introduces the use of the VideoJS video player instead of the default HTML5 offering.

The end result can be see here: http://c1.adis.ws/c/playground/step-017_-_hello-world-video-videojs

Step 1: Include VideoJS files in HTML

VideoJS has some dependant JS & CSS. Below is an example with the latest files at the time of production.

Step 2: Amend Handlebars template to match VideoJS Structure 

VideoJS has required some extra classes and data attributes. The below Handlesbars template takes this into consideration from http://videojs.com/getting-started/.

 

Step 3: Instantiate the VideoJS Player

Once the HTML has been created for the Video, we can instantiate the VideoJS player

Step 4: See the result

URL: http://c1.adis.ws/c/playground/step-017_-_hello-world-video-videojs

Content Authoring Developer Reference

To complement the more tutorial-driven development demonstrations, this reference digs deeper into the content type schemas that underpin Content Authoring.

 Read about Schema Structure...

Content Authoring - Schema Structure

While every schema is different according to the content type it describes, all schemas have the same overall structure as described here using a sample "Article Grid" schema as an example.

 See the complete schema code...

Schema Header

The first part of the schema definition identifies that the container is described according to the JSON schema standard, and it specifies the self-referential schema ID.

Schema Metadata

The next part of the schema definition is the metadata that describes the schema. This metadata includes the name and description of the schema plus the icon image that is used to represent it in the Content Authoring UI. It also includes details of the card that will be used to preview the content in the UI, plus the mapping between schemas fields and the displayed card fields.

Note that the text entered into the "name" field of a content type schema will be the human-readable friendly name for the schema that is displayed as a label in the UI. This text will be slugified (e.g. spaces converted to dashes and all characters made lowercase) by our system when forming the schema reference URL.

Schema Validation

The next section defines validation, in this case that the container must validate against "all of" the included definitions:

Schema Definitions

The following definitions section defines the content elements that a content editor user can populate when creating a content item, with this set of definitions also being used by the Content Authoring UI to build a schema-compliant input form for the content type described by the schema:

The schema section shown above defines the allowed content labelled "articleList" as being an "array" type comprising at least one item that complies with the validation required for a "contentLink". Besides being of type "array", the articleList is further constrained by being of semanticType "list".

A note about Inline Schemas...

The purpose of inline schemas is to include one schema's content within another schema's content "by value" in a composition arrangement, such that the lifetimes of the main content and included content are tied together... and so that the included content cannot be shared as a component of other owning content entities. This is in contrast to merely linked content that has a completely independent existence and can be shared among owning entities.

For the inline content case, the following schema code snippet shows how an inlined sub-schema can be included in an array. This includes the necessary "_interpolate": true indication that is required for inline schemas.

 Read about Schema Data Types...

Content Authoring Schema Data Types

To complement that JSON primitive data types that include numbers, strings, booleans, arrays and objects, we support a range of semantic data types that further constrain and validate those primitive types. In the following schema extract, you can see how a "heading" field of type "string" is associated with the semantic type "text" that defines it as a plain text string.

In contrast, the following schema extract shows how a "Body" field of type "string" is associated with semantic type "markdown" that signifies to the Content Authoring UI and any front-end application that this text string can include Markdown mark-up syntax.

Supported Semantic Types

The list of supported semantic types is detailed below, beginning with the group of semantic types that may be applied to strings.

String Semantic Types

Semantic type text defines a natural language plain text string.

Semantic type symbol defines a non-natural-language plain text string such as a product SKU.

Semantic type markdown defines a text string marked up with Markdown syntax.

Semantic type uri defines a Uniform Resource Identifier (URI), which must be used in conjunction with “format”:“uri”.

Semantic type date-time defines a RFC3339 date, which must be used in conjunction with “format”:date-time”.

Semantic type email defines an email address, which must be used in conjunction with “format”:email”.

Boolean and Number Semantic Types

Semantic type boolean extends the "boolean" primitive type for true-false values.

Semantic type number extends the "number" and "integer" primitive types for numeric values that may have minimum and maximum allowed values, e.g.

"_semanticType":"http://semantic-type.cms.amplience.com/number",
"minimum":50,
"maximum":100

Asset Semantic Type

Semantic type asset extends the "object" primitive type to reference media assets such as images and video. When using this semantic data type you must include "allOf" validation that references the "di-asset-link" schema, and you must constrain the type of media to image (or video, or both) by adding an "enum" validation to the "mediaType" property as shown here:

 See the Image Asset code...

Array / List Semantic Types

Arrays of primitive types can be defined quite simply by associating the list semantic type with the "array" primitive type (and in this case associating the text semantic type with the "string" primitive types contained as "items" within the array):

 See the Array of Primitives code...

Taking this a stage further, arrays work by adding constraints to the items that tell the system what can go into the array. You must provide the correct semantic type for the "items” in the array; for example the semantic type asset that defines each of the array entries as a "di-asset-link" as shown here:

 See the Asset Array code...

We support mixed sets of asset / di-asset-link and content / content-link (as shown below) so that you can create an array of slides or images.

 See the Mixed List code...

  

Semantic Types Rendering in the Content Authoring User Interface

The use of semantic types allows the Content Authoring user interface to render content type input forms in particular ways, such as rendering a boolean type as a check-box or toggle control. In the case of arrays (of semantic type list), the UI can allow the user to add additional list entries (e.g. text strings or images) up to the maximum number of items allowed.

 Read about Schema Validation...

Content Authoring Schema Validation

Schema developers can specify validation for the items defined within the schema as described here. Validation serves two purposes:

  1. To constrain the values that content editor users can enter as content into form fields.
  2. To trigger the Content Authoring UI to present form fields in a particular way; e.g. as a drop-down list for enumerated items. 

Minimums and Maximums Validation

We support minLength / maxLength validation for string items, and minItems / maxItems validation for arrays. These kinds of validation are illustrated in the following schema code extract.

Note that we do not validate the validation itself. For example: where validation defines minLength and maxLength (or minItems and maxItems) to constrain form fields, we do not check that the schema developer entered valid values for those validations; i.e. that minLength < maxLength.

Combining Schema Validations with "allOf", "anyOf", "oneOf" and "not"

We support the JSON Schema "allOf", "anyOf", "oneOf" and "not" keywords for combining schemas. These keywords correspond with traditional boolean AND, OR, XOR and NOT operators as follows:

allOf (AND) means that the given data must be valid against all of the included sub-schemas.

anyOf (OR) means that the given data must be valid against at least one of the included sub-schemas.

oneOf (XOR) means that the given data must be valid against exactly one of the included sub-schemas.

not (NOT) means that the given data is valid if it does not validate against any of the sub-schemas.

In the following schema code for a mixed asset array, each of the array items must be oneOf an "asset" or "content"; with an "asset" item being allOf a "di-asset-link" and media type "image" whereas a "content" item must be allOf a "content-link" and content URI.

Enum Validation

When applied to string (as in the schema code shown below), the enum semantic type will cause a drop-down list to be rendered in the Content Authoring content type form.

Note that in this example it is the enum semantic type that triggers the UI to render a drop-down list, and not the JSON "enum" keyword that simply constrains the values that may be accepted for the input string. The JSON "enum" keyword may also be used in other ways to constrain items, such as in the earlier example of constraining a "mediaType" to be an "image".  

 Read about Schema Icons...

Content Authoring Schema Icons

Within the Content Authoring tool, developer-created schemas are represented by icons as shown here:

The icon used to represent a particular schema is set in the "icons" section of the "meta" section of the schema, as shown here for the "Article" content type schema:

All icons have the same base URL suffixed with the name of the particular icon image, so the paths to the other available icons would be:

You can determine the icon URL for any particular content type by opening the schema for editing in the Schema Editor, for example if you would like to reference the same icon in another content type schema.

 Read about Library Cards and Visualization...

Content Authoring Library Cards and Visualization

The Content Library displays content items using "cards" that provide preview representations as shown below. These cards offer improved content navigation and identification compared with simple content file names.

 

As with a content type schema's icon, the card that is used to visualize any content for a particular content type is defined in the "meta" section of the schema:

The uri property references the HTML page of the card that will be used to provide a preview rendering of any content for this content type schema, and the optional mapping property defines the mapping between content type fields and card display fields. Content schemas are written in JSON format and use the JSON Pointer standard for identifying a specific value, such as an image at the specified index in an array. You'll need to use this notation in your card's mapping section if you use nested content types. You can find an example in the Gallery section of the Content Authoring- Built-in Library Cards page.

See the cards tutorial for more details of how to configure cards for your content.

While there are many built-in cards, it is also possible to define your own, and to host them pretty much anywhere that is accessible via a URI. For a list of the built-in cards together with examples of their use, see Content Authoring- Built-in Library Cards

Visualization

The basic library cards idea can be extended with a visualization. A visualization provides a preview of content that is as close as possible to how it will appear on your production site. If a visualization has been added to a content schema, then it will be displayed in the content editing window, as shown below. You can use the device menu to preview the content at different sizes or detach it and view it in its own window.

A visualization is a specific category of card and is specified in the "card" section of the content type schema. When a visualization is added for a content type, the card section must be represented as an array and the uri parameter for the visualization entry will be the uri of the web app that implements the visualization. In the example below, the visualization uri is 

https://s3-eu-west-1.amazonaws.com/amp-product/tutorials/Visualizations/viztutorialpoi.html

Note the first entry, specifying the library card, must include entries for id, category and default: 

"id": "defaultCard",
"category": "card",
"default": true,

otherwise the visualization will not be displayed.

See the visualizations tutorial for a step by step guide to adding visualizations to your content types.

 

 Read about the Content Delivery API and SDK...

Content Authoring Delivery API and SDK

The Content Delivery API and SDK together allow you to retrieve published content to be rendered by a front-end application.

Delivery API

The Delivery API allows you to access published content via a simple HTTP GET request, which returns the content in JSON-LD format.

Request

The Delivery API can be accessed via the URL https://c1.adis.ws/cms/content/query? suffixed with the a URL encoded query of the following form (where id is the unique identifier of the content to be retrieved) :

{"sys.iri": "{id}"}

Here is the AJAX / jQuery client-side Javascript code for a fully formed content query:

The 'scope' parameter specifies the objects that are returned by the API:

scope 
treereturns the full dependency tree
rootreturns only the root object

if no value is specified, then scope will be set to 'tree'.

Note that whereas this example uses “sys.iri”:”iri” to query a single content-identifying IRI, it is possible instead to use the MongoDB syntax "$in" operator to query a list of IDs as shown in this JSON code:

The ID of a particular content object, plus the URL used to access it via the API, can be determined by clicking the "Get Asset Link" (chain-link) icon for the content in the Content Library as shown here:

Response

Clicking the "View LIve Delivery URL" link shown in the previous picture causes the content to be queried and displays the result in a web browser window like this:

The API response uses the lightweight linked data JSON-LD format (see http://json-ld.org/) that allows applications to follow links between one piece of data and another. The results are placed in an @graph array, which is easier to see in the following screenshot of the Delivery API test application at http://apps.dev-artifacts.adis.ws/cms-delivery-playground/master/3/index.html?apiBase=https://c1.adis.ws/cms/content/query:

 

SDK

The SDK exposes an inlineContent method on the amp namespace which flattens the content graph returned as the API response. It can be invoked from Node or a web browser (>=IE8) as follows.

Node

var amp = require('cms-javascript-sdk');
amp.inlineContent({{content}});

Browser

<script type="text/javascript" src="cms-javascript-sdk.min.js"></script>
<script type="text/javascript">
amp.inlineContent({{content}});
</script>

Combined API and SDK Example

The following combined code snippet retrieves content via the API, inlines it using the SDK, and logs out the content to the browser console log.

 See the combined API and SDK code sample...

For a detailed step by step example, see the Content Authoring Developer Tutorial Part 1: Quick Start

Delivery API - Default Cache Settings

The Amplience CDN architecture caches delivery API responses in the following manner:

  • Edge Servers - 300 seconds (5 minutes)
  • Mid Tier Servers - 300 seconds (5 minutes)

Therefore, when updating existing content, the maximum time you will have to wait to see the updated directly from the delivery API is 10 minutes

 Read about Dynamic Media...

Content Authoring Dynamic Media

Dynamic Media allows dynamic imaging and dynamic video to be delivered into any channel and device format from a single master asset.

URL Structure

Images and video are retrieved using a simple URL structure comprising the media type, account name, and the name of the asset you wish to return.

Images: /i/{account}/{image}

Videos: /v/{account}/{video}

Sets: /s/{account}/{set}

Parameters

A range of parameters can be appended to the URL in order to dynamically modify the retrieved asset(s). Such modifications are performed on-the-fly without affecting the original asset, and there are no restrictions on how many parameters may be appended to each URL.

Parameter example: /i/{account}/{image}?{list of parameters}

Real life example: /i/playground/flower1?w=300

Multiple Parameter example: /i/playground/flower1?w=300&crop=100,100,200,200

More Information

More information about Dynamic Media can be found at http://playground.amplience.com/di/app/#/intro.

 Read about Front-End Developer Tooling...

Content Authoring Front-End Developer Tooling

Upon selecting the "Get content ID / link" icon (1) for a content item, the pop-up dialog includes a hyperlink to "View in JSFiddle" (2).

Clicking the link allows you to use the JSFiddle online editor (as shown below) to make changes to front-end HTML, Javascript and CSS code and to see the results of those changes.

 Running the Fiddle and then clicking on the "View JSON" message allows you to see JSON-LD content response, like this:

 

 Read about the Built-in Library Cards...
Cards are used in Content Authoring to present a visual summary of content in order to make it easier to identify in the content library. Content Authoring provides a set of built in cards that show content in different ways, allowing you to choose an appropriate card for each content type. 

As explained in the Cards and Visualisations tutorial, the card to use for a particular content type is specified in the content type schema, by including that card's URI. Each card is designed to display different content elements. Some cards include a mixture of images and text, while the Handlebars card is much more flexible, allowing you to use a handlebars template and CSS file to render your own representation of the content.

Mapping

To use each card, apart from Handlebars, you need to specify a 'mapping' section in the content schema. This section maps the content elements defined in the content schema, to the appropriate sections of the card. For example, if a card displays an image, then the 'image' element might be mapped to the "background" element in your content schema, as shown below.

Content schemas are written in JSON format and use the JSON Pointer standard for identifying a specific value, such as an image at the specified index in an array. You'll need to use this notation in your card's mapping section if you use nested content types, such as a carousel that contains an array of slides. Each slide would then contain an image and you'd access each image as shown in the example below. In this example, the slides are contained in an array called "imageblock". The complete example is shown in the Gallery section below.

Examples of each of the built-in cards, together with the mapping section and example content schemas are shown below.

 

The library cards are updated on a regular basis to include performance improvements and add new features. To ensure that you are using the latest version of each card, use the URIs shown on this page. These URIs include 'latest' in the card's path.

Gallery

Gallery is the library card added to the schema by default when you create a new content type. It's also what we use in the tutorial.

uri:  //apps.dev-artifacts.adis.ws/cms-cards/master/latest/gallery/index.html

mapping: headline, image0. Optionally image1, image2, image3

The gallery card displays a piece of headline text, together with between 1 and 4 images. The images are arranged in a grid layout. In the first example, we're just showing the background image and the headline.

To use the Gallery card, adding headline and image 0 (and optionally image1,2 and 3) to the card section of the content schema.

The complete content schema used in this example is shown below.

 

 Click here for the content schema...


Displaying multiple images

To display two or more images using the gallery card, add the images to the mapping section. In this example we are using a carousel that contains a list of slides, each containing a single image. This uses the JSON Pointer standard as explained in the introduction.

This specifies that four images should be displayed. The gallery card will layout these images in a grid.

 Click here for the content schemas...
 Click here to expand the carousel schema..
 Click here to expand the slide schema...

 

 

 

Text

The Text library card displays the headline text centred on the card rendered at 24 point. This card is useful in the cases where you want to identify a piece of content based on its text rather than images.

uri:  //apps.dev-artifacts.adis.ws/cms-cards/master/latest/text/index.html

mapping: headline

To use the Text card the only field required in the mapping section is the headline.

The content schema for this example is shown below.

 Click here for the content schema...

Summary

The Summary card displays a headline and subheading, together with an image. 

uri:  //apps.dev-artifacts.adis.ws/cms-cards/master/latest/summary/index.html

mapping: headline, sub, image

To use the Summary card include the mapping for the headline, sub and image. Note that the image must be included for the library card to display correctly.

The content schema for this example is shown below.

 Click here for the content schema...

Photo

uri: //apps.dev-artifacts.adis.ws/cms-cards/master/latest/photo/index.html

mapping: image

The Photo library card just shows a single image, centred on and filling the card.

To use the Photo card just include the mapping for image in the content schema. 

The content schema for this example is shown below.

 Click here for the content schema...

Handlebars

uri: //apps.dev-artifacts.adis.ws/cms-cards/master/latest/handlebars/index.html

mapping: For the Handlebars card, no mapping is required, since the card is rendered using a handlebars template and CSS file.

In this example we have chosen to render the headline, sub heading, background image and the "call to action" button. While the button is not functional in the library card, it does provide a more accurate representation of the content and shows the flexibility you have when using a handlebars template.

To use the handlebars card, add a "params" section to the card definition in the content schema:

cssThe URL for the CSS file. This is an optional parameter
templateURLThe URL for the handlebars template

Further optional parameters can be specified:

preRenderThe URL for a JavaScript file to be run before the card is rendered
postRenderThe URL for the JavaScript file to be run after the card is rendered

The complete content schema, CSS file and handlebars template used in this example are shown below:

 Click here for the content schema...

 

 

 Click here for the Handlebars template...
 Click here for the CSS file...
 Read about Creating Your Own Library Cards...

 

This page provides background reference information for developers who want to create their own library card for use in the Content Library in Content Authoring. If you wish to create your own card, please contact your Customer Success Manager for more details.


About Cards

As discussed in the Cards and Visualisations tutorial, Cards in the Content Library provide a graphical representation of a piece of content. In most cases developers will use one of the built-in cards such as the Gallery or Summary card and specify which card to use in the Content Type schema. For more advanced uses there is also a handlebars card that provides you with a lot of flexibility and allows you to add your own CSS styling, handlebars template and JavaScript code to render content. The built-in cards are described in detail in the built-in cards page. The built-in cards are generally sufficient for most cases, but if you use your own templating technologies or want to use some specific libraries of code, then there may be cases where you want to write your own library card.

This page takes you through step but step the process of creating your own library card, using a simple version of the Gallery card as an example.

The card to use to display content is specified in the 'card' section of the content type schema. In this example we have created a custom card called 'tutorialcard', uploaded this to AWS and referenced it from the schema. The card consists of an HTML file, together with some CSS and JavaScript. The card accepts mapping elements: a background image and some headline text to be displayed below the image.

When a library card is shown in the Content Library, the card web app is responsible for rendering content within the an iFrame on the card itself. This area excludes the title, the publish status icon and the contextual menu and the custom tutorial card is shown with a blue border in the image below.

When you write your own card, you will be responsible for rendering a representation of the content within this iFrame. Note that cards need to be designed to be responsive, since size of the cards will vary as the user grows or shrinks the content library window. 

Step 1: Decode URL

Cards are single page applications that adhere to a a basic URL convention

<URL of card>?src=<encoded url of content API GET request>

This URL includes sufficient information to render its representation of the content within the iFrame.

An example of this URL is shown below.

 Click here for an example URL with query parameters…

As you can see the URL is quite long. The reason for this is that the encoded URL represents the URL of the GET request to be made to the Delivery API and also includes a time based, single use token that is used to retrieve the content.  

The 'src' element is then extracted from the URL and decoded. An example of a decoded 'src' element is shown below.

 Click here for an example decoded src element...
 Click here for some sample code…
This code will extract the query component from the URL and decode it using the standard JavaScript decodeURIComponent function. The query is then sent as an AJAX Get request to the Content API.

 

Step 2: Request Content

The decoded URL is then sent as the content of an AJAX GET request to the Delivery API. An example of the code of some standard code to send the Get request is shown below.

 

 Click here for an example AJAX GET request...

This code uses the Q promise library, but you probably have your own code for making an AJAX request and handling the result.

Assuming the request is successful, the JSON content of the item to be shown on the card is returned, including the JSON schema. The schema is required because it contains the 'mapping" section that specifies which content elements to include on the card.

An example of the response from the Content API is shown below. 

 Click here for an example of the JSON content and schema...


Step 3: Flatten Content

The content graph is then converted into a content tree using the amp.inlineContent method. Here's an example of the converted content tree:

Here is some example code that shows how to build the content tree. Note that the content schema is also stored, since this will be needed to map the content elements to be displayed on the card to the actual content.

 Click here for some sample code…

This code takes the content returned by the AJAX Get request and returns the flattened content and the schema.

Step 4: Store the schema

'schemas' is returned as an array, so you will first need to retrieve the schema that applies to this piece of content. Use the 'type' field as the index into the schemas array. For this content it is:

  "@type": "http://schema.cms.amplience.com/448506a3-cf6b-4103-b592-697da7195ac7"

So we can retrieve the schema we need using the following code:

var schema = schemas[content["@type"]];

And then access the mapping:

var map = schema.meta.card.mapping

and create the map as  explained in Step 5 below.

Step 5: Extract mapping information

As covered in the Cards & Visualisations tutorial, in the schema when you specify the card to be used for the content, you also include mapping information. This tells the card which content element to map to which area within the card. In our example we just specify two mappings: headline and image. 

 

This mapping is now used to set headline and strapline to the actual assets to be displayed on the card. The mapped content will look something like:

To produce this mapping we combine the content with the mapping parameters defined in the content schema. The code below provides an example of how to do this.

The example uses the standard JSON.pointer implementation to combine the mapping and the content into an array of key value pairs. The key being the mapping parameter and the value the content it maps to, in this example the URL of the image and the headline text. You might choose a different technique to produce the mapped content that's shown above.

In the example code, the map parameter is the mapping from the content schema as shown in Step 4.

while content is the inlined content from Step 3.
 Click here for some code that creates the map..

 

Step 6: Render card content

Once the content map is produced, each element is then extracted and added to the card. In this example the background image URL is:

https://ext1.adis.ws/url/portal/f3cf94f8-5486-4a18-8451-a99f99c2fea9 

The following code shows how to construct this URL from the mapped content by combining the defaultHost, endpoint and name fields.

 Click here for example code to construct the image URL...

Once the URL is constructed it can then be added to the card. One approach is to represent the image with a CSS element and then set that element's 'src' parameter to the image URL. In the simplified code below the CSS element is '.image':

    imgElm =  document.querySelector('.image');
imgElm.src = url

You would also need to include a default image or some text to be used if the background image cannot be loaded. To apply Dynamic Imaging commands to the image, just add these to the URL as query parameters in the normal way.

Adding the headline text would take a similar approach, retrieving a 'headline' CSS element and setting this to the text from the mapped content:

document.querySelector('.headline').innerHTML = mapped.headline;

The text would need to be "sanitised" to remove any potentially dangerous characters. Some sample code to do this can be found here.

 

 

  • No labels