AEM: Technical Gude

This is technical guide for setting up an AEM (Adobe CQ) integration in Kapost.

To make the most of it, you need to be familiar with the Kapost interface and terminology, suplemented by a healthy dose of knowledge about the internals of AEM.

Getting Started

Every AEM setup in the wild operates as two separate "entities". One is called the 'Author Instance' while the other is called the 'Publish Instance'.

Kapost communicates only with the 'Author Instance' by using the standard compliant CRX/JCR API. This means that the instance has to be accessible from the outside world. In most cases this will not be possible due to various security measures; in order to aleviate this, Kapost can provide you with a single static IP address which you can whitelist on your end and Kapost will route all traffic through this single endpoint.

To enable this feature for your instance, please contact Kapost Support.

Kapost needs a user with read & write access, it doesn't have to be an "absolute admin" and it is possible to limit this user to a certain 'sub-tree', if absolutely necessary.

Once the 'Author Instance' is accessible and the user has been created, it's now possible to setup the "integration" by going to the Kapost "App Center".

Mapping

The actual mapping happens on an individual Content Type basis. Please note that only Content Types with the body type set to HTML and Any File are supported.

Do not use leading or trailing slashes in any of the mappings.

  • content/blog (good)
  • /content/blog (bad)
  • content/blog/ (bad)
  • /content/blog/ (bad)

Required Fields

Like their name suggests, these fields are mandatory.

Parent

The parent is the absolute parent node, every other mapping is relative to the path defined in this field. Usually this will be just a simple value like content.

Permalink

The permalink is the actual path component of the URL pointing to a "post" or "file".

  • blog/%slug%.html
  • files/%file:name%

This will be "joined" with the 'Author' or 'Publish' instance URL during publishing. Please see the section about Publishing to learn more.

Body

The body is the HTML contents of a "post" or the binary blob of a "file".

  • blog/%slug%/body
  • blog/%file:name%/jcr:content/jcr:data

Optional Fields

Like their name says, optional fields, well they are optional. This means that they can be left blank if not used.

Some optional fields like tags, categories or SEO will only show up for mapping, if the respective features are turned on in the instance settings.

  • blog/%slug%/title

Custom Fields

All custom field types available in Kapost can be mapped to "node" properties in AEM.

Constants

Constants are any properties your node needs that are not user definable. For example the jcr:primaryType of a node.

It is possible to add any number of constants. Their order does not matter because they will get sorted automatically.

Variables

There are various variables that you can use in both the path and the value components when mapping.

  • %year% - the current year
  • %month% - the current month
  • %day% - the current day
  • %date% - full ISO8601 date
  • %title% - the title of the piece of content
  • %slug% - URL friendly version of the the %title%

When the "body type" is Any File the following extra variables are made available.

  • %file:name% - filename with extension (test.png)
  • %file:type% - content type / mime type (image/png)

When the body type is HTML, images that have been inserted into the HTML can be mapped as well and the following extra variables are exposed to make it possible:

  • %image:name%
  • %image:type%
  • %image:title%
  • %image:caption%
  • %image:alt%
  • %image:data%

User defined custom fields are also made available as variables. The general pattern of referencing a custom field is in the form of custom_field_type:{custom_field_name} respectively custom_field_type:{custom_field_name}:property_name.

The custom_field_type can be one of these: text, select, multiselect, date, image, file.

The custom_field_name is the Field Name not the Display Name.

Please consult the following examples:

  • %text:{intro}%
  • %select:{product_type}%
  • %file:{some_file}:name%
  • %file:{some_file}:type%
  • %image:{some_image}:name%
  • %image:{some_image}:type%
  • %image:{some_image}:title%
  • %image:{some_image}:caption%
  • %image:{some_image}:alt%

Examples

Take a look at a couple of example mappings below.

Basic HTML mapping
Fields
Name Value
Parent content
Permalink blog/%year%/%month%/%slug%.html
Body blog/%year%/%month%/%slug%/text
Title blog/%year%/%month%/%slug%/title
Constants
Path Value
blog/%year%/%month%/%slug%/jcr:primaryType nt:unstructured
blog/%year%/%month%/%slug%/sling:resourceType blog
Basic HTML mapping with variable path based on a custom field value
Fields
Name Value
Parent content
Permalink blog/%select:{product}%/%year%/%month%/%slug%.html
Body blog/%select:{product}%/%year%/%month%/%slug%/text
Title blog/%select:{product}%/%year%/%month%/%slug%/title
Constants
Path Value
blog/%select:{product}%/%year%/%month%/%slug%/jcr:primaryType nt:unstructured
blog/%select:{product}%/%year%/%month%/%slug%/sling:resourceType blog
Advanced HTML mapping with Inline Images and Custom Fields
Fields
Name Value
Parent content
Permalink blog/%year%/%month%/%slug%.html
Body blog/%year%/%month%/%slug%/text
Title blog/%year%/%month%/%slug%/title
Thumbnail blog/%year%/%month%/%slug%/thumbnail/jcr:content/jcr:data
Text Blurb blog/%year%/%month%/%slug%/blurb
Constants
Path Value
blog/%year%/%month%/%slug%/jcr:primaryType nt:unstructured
blog/%year%/%month%/%slug%/sling:resourceType blog
blog/%year%/%month%/%slug%/thumbnail/jcr:primaryType nt:file
blog/%year%/%month%/%slug%/thumbnail/jcr:content/jcr:primaryType nt:resource
blog/%year%/%month%/%slug%/thumbnail/jcr:content/jcr:mimeType %image:{thumbnail}:type%
blog/%year%/%month%/%slug%/images/%image:name%/jcr:primaryType nt:file
blog/%year%/%month%/%slug%/images/%image:name%/jcr:content/jcr:primaryType nt:resource
blog/%year%/%month%/%slug%/images/%image:name%/jcr:content/jcr:data %image:data%
blog/%year%/%month%/%slug%/images/%image:name%/jcr:content/jcr:mimeType %image:type%
Advanced HTML mapping with Inline Images and Custom Fields (DAM)
Fields
Name Value
Parent content
Permalink blog/%year%/%month%/%slug%.html
Body blog/%year%/%month%/%slug%/text
Title blog/%year%/%month%/%slug%/title
Thumbnail dam/blog/%image:{thumbnail}:name%/jcr:content/renditions/original/jcr:content/jcr:data
Text Blurb blog/%year%/%month%/%slug%/blurb
Constants
Path Value
blog/%year%/%month%/%slug%/jcr:primaryType nt:unstructured
blog/%year%/%month%/%slug%/sling:resourceType blog
dam/blog/%image:{thumbnail}:name%/jcr:primaryType dam:Asset
dam/blog/%image:{thumbnail}:name%/jcr:content/jcr:primaryType dam:AssetContent
dam/blog/%image:{thumbnail}:name%/jcr:content/cq:name %image:{thumbnail}:name%
dam/blog/%image:{thumbnail}:name%/jcr:content/cq:parentPath /content/dam/blog
dam/blog/%image:{thumbnail}:name%/jcr:content/renditions/original/jcr:primaryType nt:file
dam/blog/%image:{thumbnail}:name%/jcr:content/renditions/original/jcr:content/jcr:primaryType nt:resource
dam/blog/%image:{thumbnail}:name%/jcr:content/renditions/original/jcr:content/jcr:mimeType %image:{thumbnail}:type%
dam/blog/images/%image:name%/jcr:primaryType dam:Asset
dam/blog/images/%image:name%/jcr:content/jcr:primaryType dam:AssetContent
dam/blog/images/%image:name%/jcr:content/cq:name %image:name%
dam/blog/images/%image:name%/jcr:content/cq:parentPath /content/dam/blog/images
dam/blog/images/%image:name%/jcr:content/renditions/original/jcr:primaryType nt:file
dam/blog/images/%image:name%/jcr:content/renditions/original/jcr:content/jcr:primaryType nt:resource
dam/blog/images/%image:name%/jcr:content/renditions/original/jcr:content/jcr:data %image:data%
dam/blog/images/%image:name%/jcr:content/renditions/original/jcr:content/jcr:mimeType %image:type%
Basic File mapping
Fields
Name Value
Parent content
Permalink files/%file:name%
Body files/%file:name%/jcr:content/jcr:data
Constants
Path Value
files/%file:name%/jcr:primaryType nt:file
files/%file:name%/jcr:content/jcr:primaryType nt:resource
files/%file:name%/jcr:content/jcr:mimeType %file:type%
Advanced File mapping (DAM)
Fields
Name Value
Parent content
Permalink dam/files/%file:name%
Body dam/files/%file:name%/jcr:content/renditions/original/jcr:content/jcr:data
Constants
Path Value
dam/files/%file:name%/jcr:primaryType dam:Asset
dam/files/%file:name%/jcr:content/jcr:primaryType dam:AssetContent
dam/files/%file:name%/jcr:content/cq:name %file:name%
dam/files/%file:name%/jcr:content/jcr:mimeType %file:type%
dam/files/%file:name%/jcr:content/cq:parentPath /content/dam/files
dam/files/%file:name%/jcr:content/renditions/original/jcr:primaryType nt:file
dam/files/%file:name%/jcr:content/renditions/original/jcr:content/jcr:primaryType nt:resource
dam/files/%file:name%/jcr:content/renditions/original/jcr:content/jcr:mimeType %file:type%

Publishing

In Kapost a piece of content can be "synced" or "published" into AEM by clicking the Publish button. This will present the user with two choices:

  1. publish (as live)
  2. publish as draft

When publishing (as live) Kapost "pushes" the content into the 'Author Instance', creating or updating as necessary and then automatically replicates (read: activates) it to the 'Publish Instance', using the standard compliant replication API available in AEM.

On the other hand, when publishing as draft, the content will not be replicated and will only be created or updated in the 'Author Instance' and can be published (as live) at a later time.

If a piece of content has been published and it needs to be updated then it is possible to republish it, with the process being identical to the one presented above.

The permalink to the "post" or "file" will point to the 'Author' or 'Publish' instance depending on which 'publish' action was used.