Skip to main content

Migration Center ANS Mapper: Creating a story with multiple related images

In many cases, you may want to ingest a single source document into Arc XP that includes related objects, for example, a story with several related images. The Migration Center ANS Mapper supports this typical workflow, but it requires you to pass the relevant parts (images and text) of your source document to specific templates in order to transform and load correctly. The directions in this document help guide you through the process. 

Before you proceed, keeping the following items in mind: 

  • Images (Photo Center) and stories (Composer) are separate entities in Arc XP

  • Both have unique IDs (ANS ID or _id) and data formats

  • Stories can reference images, and images can appear in multiple stories

  • Arc XP automatically retrieves de-normalized image data when creating a story for convenience for when retrieving from Content API

  • Ideally, create images before referencing them in stories (not mandatory)

This example shows minimum ANS for an image reference in a story:

{
    "type": "reference",
    "referent": {
        "id": "RW6FY26ERFJYVXRCUXGPIAOWHE",
        "type": "image"
    }
}

Based on the this example, to create an image reference in ANS of type story, all that is necessary is to know the _id of the image.

Because you control how ANS IDs are created in your Migration Center mapping templates, you must ensure that the method used always produces the same _id when given the same source ID. The generateArcHash function was built for this purpose.  

Provide the generateArcHash function a consistent parameter uniquely identifying the source content both when creating the ANS _id to create the image and when creating a reference to that image.  

First, create a map that maps the smallest part of the source content that represents a single image, to be transformed into ANS of type image. Migration Center then submits the transformed image ANS to Photo Center to create that content. The image ANS output when submitting to your Sandbox environment might look something like this:

{
    "id": "RW6FY26ERFJYVXRCUXGPIAOWHE",
    "version": "0.10.7",
    "type": "image",
    "owner": {
        "id": "sandbox.<yourorgid>"
    },
    "additional_properties": {
        "originalName": "imageName.jpg",
        "originalUrl": "https://example.com/imageName.jpg"          
    }
}

Then create a second ANS mapping template to generate the ANS of type story that holds a reference to the created image(s). You can reference an image in only certain parts of a story’s ANS, including promo_items.basic and content_elements. Refer to the ANS Schema for full details.

Example

As mentioned previously, you need two maps: a story and an image map.

Your story map must convert the images to something like this for the respective field you are mapping.

{
    "type": "reference",
    "referent": {
        "id": "RW6FY26ERFJYVXRCUXGPIAOWHE",
        "type": "image"
    }
}

While your image map must generate ANS that looks similar to this.

{
    "id": "RW6FY26ERFJYVXRCUXGPIAOWHE",
    "version": "0.10.7",
    "type": "image",
    "owner": {
        "id": "sandbox.<yourorgid>"
    },
    "additional_properties": {
        "originalName": "imageName.jpg",
        "originalUrl": "https://example.com/imageName.jpg"          
    }
}    

Let’s assume the script is using the source data:

{
...story metadata,
  id: 'the id of the story',
  images: []
}
import requests
from jmespath import search as jq

storyMapId = 123
imageMapId = 456

def get_content():
    url = "Your API"
    response = requests.request("GET", url)
    return response.json()

def send_source_to_mc(item, mapId):
    // assume we pass in the source fields in the url.
    url = "https://api.{orgId}.arcpublishing.com/migrations/v3/content/source?sourceId={}&sourceType={}&groupId={}".format(
        sourceId, sourceType, groupId)
    payload = json.dumps({
        "sourceContent": item,
        "sourceAdditionalProperties": {
            "transform": {
                "mapId": "{}".format(mapId),
            }
        }})
    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer ${token}'
    }
    requests.request("POST", url, headers=headers, data=payload)

def submit_source_to_arc():
    response = get_content()
    images = jq("images", response)
    for image in images:
        send_source_to_mc(image, imageMapId)
    send_source_to_mc(response, storyMapId)