Skip to end of banner
Go to start of banner

Transformer

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 5 Next »

In order to assist with the Data Integration (DI) efforts with 3rd party systems (ex: graphQL, Prismic, GraphCMS, BigQuery, etc), Boxalino is presenting the Data Transformer service https://boxalino-di-transformer-krceabfwya-ew.a.run.app/

Use this service to:

  1. Identify the required request BODY for content integration https://boxalino-di-transformer-krceabfwya-ew.a.run.app/transformer/view

  2. Identify the required request BODY for API request https://boxalino-di-transformer-krceabfwya-ew.a.run.app/api/view

  3. Identify if your project`s connector (headless CMS/BQ/etc) is supported. If not, please provide a service request.

INTEGRATION FLOW

  1. Review the Transformer services:

    1. is your connector type is not yet supported, please get in touch with Boxalino.

  2. Use the https://boxalino-di-transformer-krceabfwya-ew.a.run.app/transformer/view service to identify the body content requested for the API request.

  3. Identify the content types (blog, banner, categories, etc) that must be integrated from your 3rd party source.

  4. Prepare the connector options https://boxalino.atlassian.net/wiki/spaces/BPKB/pages/662536193/Transformer#CONNECTOR with content from your 3rd party system.

  5. Do a test request https://boxalino.atlassian.net/wiki/spaces/BPKB/pages/662536193/Transformer#TEST-REQUEST

  6. Prepare the mapping https://boxalino.atlassian.net/wiki/spaces/BPKB/pages/662536193/Transformer#MAPPING for each content type you want to export.

  7. Do a sample request https://boxalino.atlassian.net/wiki/spaces/BPKB/pages/662536193/Transformer#REQUEST-DEFINITION

8. Repeat step 6-7 until all desired content is part of the response.

8. Do the sync request https://boxalino.atlassian.net/wiki/spaces/BPKB/pages/662536193/Transformer#REQUEST-DEFINITION

REQUEST DEFINITION

As an integrator, please create the bellow request to the provided endpoint.

There should be a process within your own project that triggers the data sync between a 3rd party source (connector) and Boxalino.

Endpoint

full data sync

https://boxalino-di-transformer-krceabfwya-ew.a.run.app

1

 

delta data sync

TBC

2

 

instant data sync

TBC

3

Action

/sync

4

Method

POST

5

Body

use the public endpoint
https://boxalino-di-transformer-krceabfwya-ew.a.run.app/transformer/view
to check the required BODY structure for your integration use-case (it depends on the content type and connector type)

6

Headers

Authorization

Basic base64<<DATASYNC API key : DATASYNC API Secret>>

7

 

Content-Type

application/json

8

 

client

account name

9

 

mode

data sync mode: F for full

10

 

type

product, user, content, user_content, order.

if left empty - it will check for all tables with the given tm

11

 

tm

(optional) time , in format: YmdHis

technical: used to identify the documents version

12

 

ts

(optional) timestamp, must be millisecond based in UNIX timestamp

13

dev

(optional) use this to mark the content for the dev data index

This is service is currently expanding. We value our integrator`s feedback.
For further service requests and integration reviews, please get in touch with Boxalino.

BODY ELEMENTS

The API SYNC request BODY structure can be accessed in the public service https://boxalino-di-transformer-krceabfwya-ew.a.run.app/transformer/view

There should be a transformer request element per data type (ex: blog, banner, etc). The body is a list (array) of such transformer request definitions (connector, document, mapping, languages)

 Body content for a single document type sync
[
    {
        "connector": {
            "type": "prismic",
            "options": {
                "query": [],
                "method": "GET",
                "access_token": "",
                "url": "",
                "page": 1
            }
        },
        "document": {
            "type": "content"
        },
        "mapping": {
            "id": "",
            "type": "",
            "creation": "",
            "last_update": "",
            "persona_type": "",
            "persona_id": "",
            "parent_content_ids": [],
            "products": [],
            "contents": [],
            "customers": [],
            "stores": [],
            "title": [],
            "description": [],
            "short_description": [],
            "images": [],
            "link": [],
            "tags": [],
            "labels": [],
            "status": "",
            "periods": [],
            "string_attributes": {},
            "localized_string_attributes": {},
            "numeric_attributes": {},
            "localized_numeric_attributes": {},
            "datetime_attributes": {},
            "localized_datetime_attributes": {}
        },
        "languages": {}
    }
]

CONNECTOR

The connector properties are:

  1. type (select from the available options)

  2. options (gets generated based on the selected connector type)

For example, bellow is a sample of the connector properties.

"connector": {
  "type": "prismic",
  "options": {
      "query": [],
      "method": "GET",
      "access_token": "",
      "url": ""
  }
}

The options vary based on the connector type.

The connector required options should be properly described in your 3rd party system documentation (it`s a generic remote access)

MAPPING

The mapping elements depend on the document that requires to be synchronized in the Boxalino ecosystem. We expect our clients to work with headless CMS / 3rd party environments for their content sync.

The mapping exposes the Boxalino Data Structure for the requested document (ex: https://boxalino.atlassian.net/wiki/spaces/BPKB/pages/252280968/doc%2Bcontent ).

For each property, as an integrator, you have to map the connector`s output path (wildcards [*] allowed):

a) for the properties returned as “string”/single value: only one mapping is allowed (ex: id, type, creation, description, etc)

b) for the properties returned as “array” ([]) or “objects”({}), set a list with index property name (output)=> mapping path (input) :

  1. the output is the explicit type (ex: for tags, the tagging source can be tags or default) or exposed property name

  2. the input is the mapping logic (ex: all product IDs from data.product_ids[*].id are set as product_ids in localized_numeric_attributes)

Check bellow a sample for a prismic integration following the designed blog logic in our public repository:

 Prismic Mapping Sample
"mapping": {
    "id": "id",
    "type": "type",
    "creation": "first_publication_date",
    "last_update": "last_publication_date",
    "persona_type": "",
    "persona_id": "",
    "title": "data.title",
    "short_description": "",
    "description": "data.content",
    "images": "data.header_image.url",
    "link": "uid",
    "tags": {
      "default":"tags",
      "category":"data.category.tags"
     },
    "parent_content_ids": "data.category.id",
    "contents": [],
    "products": [],
    "customers": [],
    "stores": "",
    "status": "data.status",
    "string_attributes": {
      "tags": "tags",
      "category_uid": "data.category.uid"
    },
    "localized_string_attributes": {
      "slugs": "slugs",
      "alternate_language_id": "alternate_languages[*].id",
      "meta_title":"data.meta_title",
      "content":"data.content"
    },
    "numeric_attributes": {
      "position": "data.position"
    },
    "localized_numeric_attributes": {
      "product_ids":"data.product_ids[*].id"
    },
    "datetime_attributes": {},
    "localized_datetime_attributes": {}
  }

At Boxalino, we try to map the way our client expects for a headless integration to work.

For this reason, if your connector integration libraries allows for content to be accessed as HTML or text (ex: data.content) - this is as well possible.

In the above sample:

  1. data.content is a RichText (editor) input

  2. when using the mapping “description”:data.content - it will be exported as TEXT

  3. when adding the mapping for localized_string_attributes - it will be exported as HTML.


The connector response returns the requested content (results) in the following:

 Prismic Response object
{
  "id": "YJJzXhAAACEAXhBY",
  "uid": "feines-haar-wir-haben-die-besten-frisuren-im-2021",
  "type": "blog",
  "href": "https://rtux-integration.cdn.prismic.io/api/v2/documents/search?ref=YKzPhhEAACEAldeL&q=%5B%5B%3Ad+%3D+at%28document.id%2C+%22YJJzXhAAACEAXhBY%22%29+%5D%5D",
  "tags": [
    "haare",
    "parfum"
  ],
  "first_publication_date": "2021-05-05T10:28:57+0000",
  "last_publication_date": "2021-05-25T10:20:12+0000",
  "slugs": [
    "feines-haar-wir-haben-die-besten-frisuren-im-2021-fur-sie"
  ],
  "linked_documents": [],
  "lang": "en-de",
  "alternate_languages": [
    {
      "id": "YJKjqxEAACMAE292",
      "uid": "cheveux-fins-nous-avons-les-meilleures-coiffures-pour-vous-en-2021",
      "type": "blog",
      "lang": "fr-ch"
    }
  ],
  "data": {
    "status": true,
    "title": [
      {
        "type": "heading2",
        "text": "Feines Haar? Wir haben die besten Frisuren im 2021 für Sie!",
        "spans": []
      }
    ],
    "meta_title": [],
    "content": [
      {
        "type": "paragraph",
        "text": "Feines Haar kann sich manchmal als echte Herausforderung darstellen. Dünn, luftig und keine Griffigkeit. Wenn man dann noch eine Frisur stylen will, liegen die Nerven meist blank. Ich bin der Sache auf den Grund gegangen und habe unsere Expertin gefragt. Erfahren Sie im Interview mit Stylistin und Geschäftsführerin vom PerfectHair.ch Salon am Obertor, auf was Sie sich besonders achten sollten, wie Sie feines Haar am besten stylen und pflegen können und welche Frisuren-Trends wir im Jahr 2021 erwarten dürfen.",
        "spans": [
          {
            "start": 0,
            "end": 513,
            "type": "strong"
          }
        ]
      },
      {
        "type": "heading2",
        "text": "Was ist feines Haar?\n",
        "spans": []
      },
      {
        "type": "image",
        "url": "https://images.prismic.io/rtux-integration/5c6b6741-b587-495f-a123-ac3eda053eec_feines-haar-2.jpg?auto=compress,format",
        "alt": null,
        "copyright": null,
        "dimensions": {
          "width": 1280,
          "height": 780
        }
      },
      {
        "type": "paragraph",
        "text": "Unter feinem Haar versteht man eine (im Vergleich zu einem durchschnittlichen Haar) eher dünnere Haarstruktur. Viele Frauen die feines Haar haben, beschreiben Ihre Mähne oft als luftig, strohig oder gar dünn.",
        "spans": []
      },
      {
        "type": "paragraph",
        "text": "Um es in Zahlen auszudrücken: Der Durchmesser einer einzelnen Strähne bei feinem Haar liegt bei nicht mehr als 0,04 Millimeter. Ein „normales“ Haar ist hingegen etwa 0,05 bis 0,07 Millimeter breit. Als dickes Haar wird alles über 0,07 Millimeter bezeichnet.",
        "spans": [
          {
            "start": 111,
            "end": 127,
            "type": "strong"
          }
        ]
      },
      {
        "type": "heading2",
        "text": "Das Experten-Interview",
        "spans": []
      },
      {
        "type": "heading3",
        "text": "Liebe Jenny, wie lange arbeitest du schon bei PerfectHair.ch und was ist deine Tätigkeit?",
        "spans": []
      },
      {
        "type": "paragraph",
        "text": "Ich habe bereits meine Berufslehre als Haarstylistin/ Coiffeuse bei PerfectHair.ch absolviert und bin seit Anfang an dabei. Heute darf ich den Salon am Obertor in Winterthur leiten und betreue unser Team von insgesamt 6 Personen. ",
        "spans": []
      },
      {
        "type": "heading3",
        "text": "Was gehört zu deinem Kerngeschäft bzw. welche Behandlungen führst du am meisten durch?",
        "spans": []
      },
      {
        "type": "paragraph",
        "text": "Ich würde sagen, dass die Behandlungen welche ich am meisten durchführe, definitiv Balayage und Farbtechniken sind. Also alles rund ums Thema Farbe und Farbverlauf gehört zu meinen \"Haupttätigkeiten\". Natürlich beruht sich meine Arbeit aber auf Vielfalt und Diversität. Also vom Haare schneiden bis zur extravaganten Frisur ist alles dabei. ",
        "spans": [
          {
            "start": 83,
            "end": 109,
            "type": "strong"
          }
        ]
      }
    ],
    "header_image": {
      "dimensions": {
        "width": 1280,
        "height": 780
      },
      "alt": null,
      "copyright": null,
      "url": "https://images.prismic.io/rtux-integration/f6562824-6e6d-4cf9-9812-1d1acf87e4cf_TrendsQ1NE5gfuUVPnA_1280x1280%402x.jpg?auto=compress,format"
    },
    "category": {
      "id": "YJE1vRAAACEAWG7G",
      "type": "category",
      "tags": [
        "magazin"
      ],
      "slug": "magazin",
      "lang": "en-de",
      "uid": "magazin",
      "link_type": "Document",
      "isBroken": false
    },
    "product_ids": [
      {
        "id": 23456
      },
      {
        "id": 34566
      },
      {
        "id": 765
      }
    ]
  }
}

LANGUAGES

This must be declared in order to map the exported language (ex: “de”) with your connector export value (ex:”en-de”).

"languages": {
  "de": "en-de",
  "fr": "en-fr"
}

AVAILABLE SERVICES

In order to allow our integrators to validate that the existing data available in the 3rd party systems is properly exported, a few helper services are available:

TEST REQUEST

Use a simple TEST request in order to validate that the connection to your configured endpoint (connector property) is valid.

curl https://boxalino-di-transformer-krceabfwya-ew.a.run.app/test \
-X POST \
-d "[{\"connector\":{\"type\":\"prismic\",\"options\":{\"url\":\"https:\/\/rtux-integration.cdn.prismic.io\/api\/v2\/\",\"access_token\":\"MC5ZSkU4SnhBQUFDSUFXSXZR.77-9QO-_vWR577-977-9HO-_ve-_ve-_vXPvv73vv71LeO-_vUNi77-9Ii3vv73vv73vv71sC2Xvv71A77-9IA\",\"query\":[\"[at(document.type, \\\"category\\\")]\"]}},\"document\":{},\"mapping\":{},\"languages\":{}},{\"connector\":{\"type\":\"prismic\",\"options\":{\"url\":\"https:\/\/rtux-integration.cdn.prismic.io\/api\/v2\/\",\"access_token\":\"MC5ZSkU4SnhBQUFDSUFXSXZR.77-9QO-_vWR577-977-9HO-_ve-_ve-_vXPvv73vv71LeO-_vUNi77-9Ii3vv73vv73vv71sC2Xvv71A77-9IA\",\"query\":[\"[at(document.type, \\\"blog\\\")]\",\"[at(document.tags, [\\\"haare\\\"])]\"]}},\"document\":{},\"mapping\":{},\"languages\":{}}]" \
-H "Content-Type: application/json" \
-H "mode: F" \
-H "type: content"

In the sample above, the following BODY is used:

 JSON body content for TEST request
[
  {
    "connector": {
      "type": "prismic",
      "options": {
        "url": "https://rtux-integration.cdn.prismic.io/api/v2/",
        "access_token": "MC5ZSkU4SnhBQUFDSUFXSXZR.77-9QO-_vWR577-977-9HO-_ve-_ve-_vXPvv73vv71LeO-_vUNi77-9Ii3vv73vv73vv71sC2Xvv71A77-9IA",
        "query": [
          "[at(document.type, \"category\")]"
        ]
      }
    },
    "document": {},
    "mapping": {},
    "languages": {}
  },
  {
    "connector": {
      "type": "prismic",
      "options": {
        "url": "https://rtux-integration.cdn.prismic.io/api/v2/",
        "access_token": "MC5ZSkU4SnhBQUFDSUFXSXZR.77-9QO-_vWR577-977-9HO-_ve-_ve-_vXPvv73vv71LeO-_vUNi77-9Ii3vv73vv73vv71sC2Xvv71A77-9IA",
        "query": [
          "[at(document.type, \"blog\")]",
          "[at(document.tags, [\"haare\"])]"
        ]
      }
    },
    "document": {},
    "mapping": {},
    "languages": {}
  }
]

SAMPLE REQUEST

You can also use the SAMPLE trigger in order to access one element of the given types.

The JSON response will be the JSONL structure as it is exported to Boxalino GCS.

Use this service to validate & check that all your data is exported as desired.

curl https://boxalino-di-transformer-krceabfwya-ew.a.run.app/sample \
-X POST \
-d "[{\"connector\":{\"type\":\"prismic\",\"options\":{\"url\":\"https:\/\/rtux-integration.cdn.prismic.io\/api\/v2\/\",\"access_token\":\"MC5ZSkU4SnhBQUFDSUFXSXZR.77-9QO-_vWR577-977-9HO-_ve-_ve-_vXPvv73vv71LeO-_vUNi77-9Ii3vv73vv73vv71sC2Xvv71A77-9IA\",\"query\":[\"[at(document.type, \\\"category\\\")]\"]}},\"document\":{\"type\":\"content\"},\"mapping\":{\"id\":\"id\",\"type\":\"type\",\"creation\":\"first_publication_date\",\"last_update\":\"last_publication_date\",\"persona_type\":\"\",\"persona_id\":\"\",\"title\":\"data.name\",\"short_description\":\"\",\"description\":\"data.description\",\"images\":\"data.header_image.url\",\"link\":\"uid\",\"tags\":{\"default\":\"tags\"},\"parent_content_ids\":\"data.parent_category.id\",\"contents\":[],\"products\":[],\"customers\":[],\"stores\":\"\",\"status\":\"data.status\",\"string_attributes\":{\"default_tags\":\"tags\",\"version\":\"version\"},\"localized_string_attributes\":{\"category_title\":\"data.category_title\",\"slugs\":\"slugs\",\"linked_language_id\":\"alternate_languages[*].id\"},\"numeric_attributes\":{\"position\":\"data.position\",\"show_in_navigation\":\"data.show_in_navigation\"},\"localized_numeric_attributes\":{},\"datetime_attributes\":{},\"localized_datetime_attributes\":{}},\"languages\":{\"de\":\"en-de\",\"fr\":\"en-fr\"}},{\"connector\":{\"type\":\"prismic\",\"options\":{\"url\":\"https:\/\/rtux-integration.cdn.prismic.io\/api\/v2\/\",\"access_token\":\"MC5ZSkU4SnhBQUFDSUFXSXZR.77-9QO-_vWR577-977-9HO-_ve-_ve-_vXPvv73vv71LeO-_vUNi77-9Ii3vv73vv73vv71sC2Xvv71A77-9IA\",\"query\":[\"[at(document.type, \\\"blog\\\")]\",\"[at(document.tags, [\\\"haare\\\"])]\"]}},\"document\":{\"type\":\"content\"},\"mapping\":{\"id\":\"id\",\"type\":\"type\",\"creation\":\"first_publication_date\",\"last_update\":\"last_publication_date\",\"persona_type\":\"\",\"persona_id\":\"\",\"title\":\"data.title\",\"short_description\":\"\",\"description\":\"data.content\",\"images\":\"data.header_image.url\",\"link\":\"uid\",\"tags\":{\"default\":\"tags\",\"category\":\"data.category.tags\"},\"parent_content_ids\":\"data.category.id\",\"contents\":[],\"products\":[],\"customers\":[],\"stores\":\"\",\"status\":\"data.status\",\"string_attributes\":{\"tags\":\"tags\",\"category_uid\":\"data.category.uid\"},\"localized_string_attributes\":{\"slugs\":\"slugs\",\"alternate_languages\":\"alternate_languages[*].id\",\"meta_title\":\"data.meta_title\",\"content\":\"data.content\"},\"numeric_attributes\":{\"position\":\"data.position\"},\"localized_numeric_attributes\":{\"product_ids\":\"data.product_ids[*].id\"},\"datetime_attributes\":{},\"localized_datetime_attributes\":{}},\"languages\":{\"de\":\"en-de\",\"fr\":\"en-fr\"}}]" \
-H "Content-Type: application/json" \
-H "mode: F" \
-H "type: content"

In the sample above, the following BODY is used:

 JSON body content for the SAMPLE request
[
  {
    "connector": {
      "type": "prismic",
      "options": {
        "url": "https://rtux-integration.cdn.prismic.io/api/v2/",
        "access_token": "MC5ZSkU4SnhBQUFDSUFXSXZR.77-9QO-_vWR577-977-9HO-_ve-_ve-_vXPvv73vv71LeO-_vUNi77-9Ii3vv73vv73vv71sC2Xvv71A77-9IA",
        "query": [
          "[at(document.type, \"category\")]"
        ]
      }
    },
    "document": {
      "type": "content"
    },
    "mapping": {
      "id": "id",
      "type": "type",
      "creation": "first_publication_date",
      "last_update": "last_publication_date",
      "persona_type": "",
      "persona_id": "",
      "title": "data.name",
      "short_description": "",
      "description": "data.description",
      "images": "data.header_image.url",
      "link": "uid",
      "tags": {
        "default": "tags"
      },
      "parent_content_ids": "data.parent_category.id",
      "contents": [],
      "products": [],
      "customers": [],
      "stores": "",
      "status": "data.status",
      "string_attributes": {
        "default_tags": "tags",
        "version": "version"
      },
      "localized_string_attributes": {
        "category_title": "data.category_title",
        "slugs": "slugs",
        "linked_language_id": "alternate_languages[*].id"
      },
      "numeric_attributes": {
        "position": "data.position",
        "show_in_navigation": "data.show_in_navigation"
      },
      "localized_numeric_attributes": {},
      "datetime_attributes": {},
      "localized_datetime_attributes": {}
    },
    "languages": {
      "de": "en-de",
      "fr": "en-fr"
    }
  },
  {
    "connector": {
      "type": "prismic",
      "options": {
        "url": "https://rtux-integration.cdn.prismic.io/api/v2/",
        "access_token": "MC5ZSkU4SnhBQUFDSUFXSXZR.77-9QO-_vWR577-977-9HO-_ve-_ve-_vXPvv73vv71LeO-_vUNi77-9Ii3vv73vv73vv71sC2Xvv71A77-9IA",
        "query": [
          "[at(document.type, \"blog\")]",
          "[at(document.tags, [\"haare\"])]"
        ]
      }
    },
    "document": {
      "type": "content"
    },
    "mapping": {
      "id": "id",
      "type": "type",
      "creation": "first_publication_date",
      "last_update": "last_publication_date",
      "persona_type": "",
      "persona_id": "",
      "title": "data.title",
      "short_description": "",
      "description": "data.content",
      "images": "data.header_image.url",
      "link": "uid",
      "tags": {
        "default": "tags",
        "category": "data.category.tags"
      },
      "parent_content_ids": "data.category.id",
      "contents": [],
      "products": [],
      "customers": [],
      "stores": "",
      "status": "data.status",
      "string_attributes": {
        "tags": "tags",
        "category_uid": "data.category.uid"
      },
      "localized_string_attributes": {
        "slugs": "slugs",
        "alternate_languages": "alternate_languages[*].id",
        "meta_title": "data.meta_title",
        "content": "data.content"
      },
      "numeric_attributes": {
        "position": "data.position"
      },
      "localized_numeric_attributes": {
        "product_ids": "data.product_ids[*].id"
      },
      "datetime_attributes": {},
      "localized_datetime_attributes": {}
    },
    "languages": {
      "de": "en-de",
      "fr": "en-fr"
    }
  }
]

  • No labels