Документация / Встраивание виджета и iframe API

Встраивание виджета и iframe API

Встройте виджет Configo во внешнюю систему и управляйте им через postMessage — конфигурация, данные о продукте и обмен правками.

Виджет Configo — это самостоятельная страница калькулятора/конфигуратора (/widget/{configurator}?token=...), предназначенная для встраивания в виде <iframe> внутрь другой системы — обычно CRM. В таком сценарии заказ и оформление остаются целиком внутри системы-хоста; используется только сам калькулятор. Эта страница описывает, как встроить виджет и как общаться с ним со страницы-хоста через postMessage.

Получение ссылки на виджет

Ссылка на виджет привязана к проекту и набору прав, закодированных в подписанный токен. Сгенерируйте её в Проект → Настройки → Виджет: выберите права, которые должны быть у встроенного виджета (показывать ли встроенную корзину, какие цены видны, переопределение/корректировка цены, печать документов), затем нажмите Сгенерировать. Вы получите:

  • Прямую ссылку — https://configo.org/widget?token=<jwt> — открывает список калькуляторов проекта, либо https://configo.org/widget/{configurator_uuid}?token=<jwt> для конкретного.
  • Код встраивания, загружающий /widget/script.js и открывающий виджет в модальном <iframe> по клику.

Токен — единственный контроль доступа: любой, у кого есть ссылка, может использовать виджет в рамках прав, с которыми она была сгенерирована. Относитесь к ней как к учётным данным; перевыпустите её, если она утечёт.

Встраивание

Вариант A — скрипт встраивания

<script>
    window.configo = {
        id: 'configo',
        btn: {class: '', style: '', text: 'Open configurator'},
        iframe: {width: '800px', height: '600px'},
        token: '<jwt>',

        // optional — sent as set_config / put_product right after the widget signals ready
        config: {mode: 'calculator'},
        product: null,

        events: {
            onReady: () => {},
            onConfiguratorLoaded: (data) => {},
            onCalculated: (product) => {},
            onAddToCart: (product) => {},
            onProduct: (product, trigger) => {},
            onConfigApplied: (type, payload) => {},
            onError: (error) => {},
        },
    }
</script>
<script id="configo" src="https://configo.org/widget/script.js" referrerpolicy="no-referrer"></script>

Это отрисовывает кнопку, открывающую виджет в модальном <iframe> (или в новой вкладке на мобильных). После загрузки скрипта доступны window.configo.setConfig(config) и window.configo.putProduct(product) — для отправки сообщений после того, как виджет уже открыт; window.configo.close() закрывает его.

Вариант B — обычный iframe

Также можно встроить /widget/{configurator}?token=<jwt> в свой собственный <iframe> напрямую, без вспомогательного скрипта. Протокол сообщений ниже работает так же — он не зависит от script.js, только от самой страницы виджета.

Протокол сообщений

Оба направления используют один и тот же конверт:

{"source": "configo", "type": "...", "payload": {...}}

Виджет принимает только сообщения такой формы; всё остальное игнорируется. Проверки origin нет ни с одной из сторон — токен, встроенный в URL виджета, является реальной границей доступа, а не канал postMessage.

События от виджета

Отправляются виджетом через window.top.postMessage(...). Если вы используете script.js, они соответствуют window.configo.events.*.

type Когда payload
ready Один раз, когда виджет смонтирован {project_uuid}
configurator_loaded Каждый раз, когда показывается или меняется конкретный калькулятор {configurator_uuid, name}
post_product При каждом пересчёте и при клике на кнопку действия {configurator_uuid, trigger: "change" | "add_to_cart", product}
config_applied После обработки сообщения set_config {ok: true}
product_applied После обработки сообщения put_product {ok: true}
error Сообщение set_config/put_product было некорректным {code, message}

product имеет одинаковую форму в каждом случае:

{
    "name": "Custom Table",
    "configuration": {"<control_id>": "<value>", "...": "..."},
    "materials": [{"uuid": "...", "name": "Oak board", "unit": "pcs", "quantity": "2.000"}],
    "parts": [ /* production sheet, same shape as calculated in the configurator */ ],
    "purchase_price": 120.5,
    "sale_price": 199
}

trigger в post_product сообщает, почему сработало событие: "change" означает, что клиент отредактировал параметр (с задержкой, так что вы не получите по сообщению на каждое нажатие клавиши), "add_to_cart" означает, что клиент нажал кнопку действия — это момент, когда нужно реально сохранить позицию в вашей собственной системе, поскольку "change" срабатывает непрерывно, пока виджет открыт.

Команды виджету

Отправляйте их в contentWindow iframe (или используйте window.configo.setConfig() / .putProduct(), если вы используете скрипт встраивания). Дождитесь ready, прежде чем отправлять что-либо — сообщения, отправленные до того, как виджет смонтировал свой слушатель, теряются.

set_config — настроить виджет. Каждое поле опционально и только переопределяет то, что вы отправляете; всё опущенное сохраняет предыдущее значение.

{
  "mode": "calculator",
  "locale": "en",
  "labels": {
    "add": "Add to order",
    "edit": "Update"
  },
  "styles": {
    "dark": true,
    "vars": {
      "--primary": "#1d4ed8"
    }
  },
  "calculator": "<configurator_uuid>",
  "product": {
    "configuration": {
      "<control_id>": "<value>"
    }
  }
}
Поле Тип Эффект
mode "full" | "calculator" "calculator" скрывает иконку корзины, сайдбар и форму оформления, независимо от права show_cart токена — используйте, когда заказы принадлежат вашей системе. "full" восстанавливает поведение по умолчанию (корзина показана, если токен это разрешает).
locale "en" | "ru" | "uk" Переключает язык интерфейса виджета немедленно, без перезагрузки.
labels {add?, edit?} Переопределяет текст кнопки действия (имеет приоритет над URL-параметром lbl_add).
styles {dark?, vars?} dark переключает тёмную тему. vars задаёт произвольные CSS-переменные на корневом элементе виджета — используйте для точечного брендирования (акцентный цвет, радиусы и т. д.), а не для полной смены темы, поскольку виджет пока не предоставляет альтернативных именованных тем.
calculator uuid Переходит к этому калькулятору. Имеет смысл только когда виджет был открыт на списке калькуляторов (/widget без uuid в пути).
product объект, похожий на продукт Удобство для предзаполнения калькулятора в том же обмене сообщениями, что и остальная конфигурация — эквивалентно отправке put_product сразу после. Требует как минимум configuration.

put_product — загрузить продукт в текущий отображаемый калькулятор, например чтобы дать клиенту отредактировать позицию, ранее сохранённую в вашей системе:

{
  "configuration": {
    "<control_id>": "<value>",
    "...": "..."
  }
}

Читается только configuration; всё остальное (цену, материалы, название) виджет пересчитывает сам. Это тот же механизм, который виджет использует внутренне при редактировании позиции в корзине.

Пример: интеграция только с калькулятором

CRM, которая владеет собственным флоу заказов и хочет использовать только калькулятор:

<script>
    window.configo = {
        token: '<jwt>',
        config: {mode: 'calculator', locale: 'ru'},
        events: {
            onProduct(product, trigger) {
                if (trigger === 'add_to_cart') {
                    // persist `product` as a line item in the CRM's own order
                }
            },
        },
    }
</script>
<script id="configo" src="https://configo.org/widget/script.js"></script>

Чтобы дать клиенту заново открыть и отредактировать ранее сохранённую позицию, откройте виджет на том же калькуляторе и отправьте put_product, как только он будет готов:

window.configo.events.onReady = () => {
    window.configo.putProduct({configuration: savedItem.configuration})
}