Content-Widgets

Content-Widgets are apps that are directly embedded into the page editor. They receive all data of available components and page data when they are updated. Content-Widgets can also send data back to the page editor to manipulate page data.

Content widgets work almost identically to external apps with the only difference that they can receive and manipulate data from the page editor. To learn how to create, register or delete a content widget or how to obtain a JWT token read the external apps documentation. Everything works here identical.

📘

Use the correct type during app creation

To create a content-widget use the type content-widget in the app creation API request.

📘

Use the correct source during message communication

Always when sending data via the postMessage method from a content-widget use the source "source": "makaira-content-widget-example-app". (content-widget instead of app).

Replace example-app with the slug of your content widget.

Receiving data from the page editor

After initializing of the iframe and always (debounced) when the user makes changes to the page in the page editor. The message from the page editor will contain the action "action": "receivePageInformation". The data object will then contain data that looks close to the following JSON object:

{
    "data": {
        "page": {
            "id": 3,
            "internalTitle": "",
            "type": "page",
            "user": "[email protected]",
            "changed": {
                "date": "2023-01-30 12:20:25.000000",
                "timezone_type": 3,
                "timezone": "UTC"
            },
            "active": {
                "de": true,
                "en": false
            },
            "searchable": {
                "de": false,
                "en": false
            },
            "seoUrls": {
                "de": "/test-seite",
                "en": ""
            },
            "metadata": {
                "de": {
                    "description": "",
                    "keywords": "",
                    "robotFollow": "follow",
                    "robotIndex": "index",
                    "seoTitle": "",
                    "title": "Testseite"
                },
                "en": {
                    "description": "",
                    "keywords": "",
                    "robotFollow": "follow",
                    "robotIndex": "index",
                    "seoTitle": "",
                    "title": "Test-Page"
                }
            },
            "relatedDocumentId": "",
            "snippetId": "",
            "essentialSnippet": false,
            "config": {
                "top": {
                    "elements": [
                        {
                            "id": "dea2b1ba-f4cc-4d0c-8893-3a12f3c497fb",
                            "component": "product-placement",
                            "name": "Produktplatzierung",
                            "properties": {
                                "de": {
                                    "active": true,
                                    "userGroups": {
                                        "Alle Benutzer": {
                                            "active": true,
                                            "isTimed": false,
                                            "activeFrom": "2023-01-30T13:38:46.491Z",
                                            "activeTo": "2023-01-30T13:38:46.491Z"
                                        }
                                    },
                                    "content": {
                                        "heading": "Headline",
                                        "text": "<p>Text</p>",
                                        "products": {
                                            "items": [
                                                {
                                                    "id": "4ed1dd97726402c552e2b64222d22d6a",
                                                    "es_id": "4ed1dd97726402c552e2b64222d22d6a",
                                                    "title": "Stickerset MIX",
                                                    "subtitle": "4001"
                                                },
                                                {
                                                    "id": "b6aba41e33349dd78c3c6d578333e6be",
                                                    "es_id": "b6aba41e33349dd78c3c6d578333e6be",
                                                    "title": "Neoprenanzug NPX ASSASSIN",
                                                    "subtitle": "3101"
                                                }
                                            ],
                                            "resolveDocuments": true
                                        }
                                    }
                                },
                                "en": {
                                    "active": false,
                                    "userGroups": {
                                        "Alle Benutzer": {
                                            "active": true,
                                            "isTimed": false,
                                            "activeFrom": "2023-01-30T13:38:46.491Z",
                                            "activeTo": "2023-01-30T13:38:46.491Z"
                                        }
                                    },
                                    "content": {
                                        "heading": "",
                                        "text": "",
                                        "products": {
                                            "items": [],
                                            "resolveDocuments": false
                                        }
                                    }
                                }
                            }
                        }
                    ]
                },
                "bottom": {
                    "elements": []
                }
            },
            "revisionParent": null
        },
        "components": [
            {
                "id": 24,
                "identifier": "contact-form",
                "name": "Contact Form",
                "fields": [
                    {
                        "uuid": "47f2397d-5bd6-4c94-bcc3-99880189f344",
                        "id": "recipient",
                        "label": "Recipient",
                        "type": "text",
                        "defaultValue": "[email protected]"
                    }
                ],
                "user": "",
                "changed": {
                    "date": "2023-01-18 13:59:48.000000",
                    "timezone_type": 3,
                    "timezone": "UTC"
                },
                "icon": "049-heading-form-cta"
            },
            {
                "id": 23,
                "identifier": "discovery-image",
                "name": "Discovery Image",
                "fields": [
                    {
                        "uuid": "e8b9bd76-9858-4546-bca9-d07e981dd14f",
                        "id": "discoveryImage",
                        "label": "Discovery Image",
                        "type": "hotspot",
                        "properties": [
                            {
                                "uuid": "989f7f26-e53e-413c-bbb6-189802c2a942",
                                "id": "product",
                                "label": "Verknüpftes Produkt",
                                "type": "documents",
                                "documentType": "product"
                            }
                        ]
                    }
                ],
                "user": "",
                "changed": {
                    "date": "2023-01-18 13:59:48.000000",
                    "timezone_type": 3,
                    "timezone": "UTC"
                },
                "icon": "043-discovery-pict-3cols-product"
            }
        ]
    },
    "selectedLanguage": "de"
}

The main three objects are page, components and selectedLanguage. components consists of an array of objects where each object is the definition of an available component in the page editor. In the example only two components are given but in a real content-widget all available components will be transmitted.

The page object contains all data that defines a page in Makaira. The most important part here is the config object which contains with top all components that are placed above the product grid and bottom all components that are placed below the product grid.

Every element / component in the page config contains some general information and a key for every language that exists in the active index of the instance. These keys belong to the objects that contain the detailed information about the components.

selectedLanguage provides the key to the language that is currently selected in the page editor by the user.

❗️

Multiple data transmits possible

We do not guarantee that the page editor only transmits the data when really fields where updated. It is therefore possible that data is transmitted several times in succession even if nothing has been changed in the data.

The data is also transmitted back when updated from within the content-widget.

Updating data of the page editor from within the content-widget

You can only update certain of the page object that you received from the receivePageInformation action. The following first-level-keys can be updated:

  • config
  • metadata
  • seoUrls
  • active
  • internalTitle
  • searchable

Manipulate the part of the object that you want to change.

Afterwards send the action updatePageInformation back to the Makaira Backend with the postMessage function. Inside of a data object provide the key key which should equal one of the given strings displayed above. The key value should be the whole updated object of the corresponding key.

❗️

Always supply the entire object that you received

You have to send back the entire object of the first-level-key that you want to update. Do not only send back the parts of object that you want to update.

If you want for example to update the active state of the first element on your page, create a copy of the elements that you received (elements are part of the config first level key). Afterwards update the active key and send back the complete object with the postMessage function.

const config = {...PAGE_DATA.config}

config.top.elements[0].properties.de.active = false
config.top.elements[0].properties.en.active = false

const message = {
  "source": "makaira-content-widget-example-app", // replace with makaira-content-widget-{YOU_APP_SLUG}
  "action": "updatePageInformation",
  "data": {
    "key": key, 
    // see: https://stackoverflow.com/questions/42376464/uncaught-domexception-failed-to-execute-postmessage-on-window-an-object-co
    "value": JSON.parse(JSON.stringify(updatedData))
  }
}

window.parent.postMessage(message, document.referrer)