• Модуль интеграций
  • Сообщество
  • Блог
Документация
Плагины и интеграцииВсе расширения для Medusa от сообществаСтартерыЗапускайте проекты быстрее с готовыми решениями
ЭкспертыПодберите специалиста для разработки и развития вашего проекта на MedusaКейсыПосмотрите примеры Medusa в продакшене и успешные внедрения
Т-Касса от Т-Банка для Medusa: приём платежей для РФ

16 октября 2026 г. · Продукт

Gorgo снижает затраты на адаптацию Medusa к локальным рынкам.

Мы разрабатываем плагины интеграции, осуществляем поддержку и развиваем сообщество разработчиков на Medusa в Telegram.

  • Ресурсы Medusa
  • Плагины и интеграции
  • Модуль интеграций
  • Стартеры
  • Эксперты
  • Кейсы
  • Medusa Чат в Telegram
  • Medusa Новости в Telegram
  • Документация Gorgo
  • Связаться с нами
  • TelegramGitHub
Плагины
P

Platform medusa

Плагин Blotout для Medusa отправляет события витрины и заказов в Qinto для first-party аналитики и идентификации, с процессом подключения в Admin.

npm install @blotout/platform-medusa
Категория
Аналитика
Создано
Blotout
Версия
0.1.0
Последнее обновление
2 недели назад
Ежемесячные загрузки
Загрузка данных
Звезды на Github
0
npmNPMGitHubGithub

@blotout/platform-medusa

By Blotout. Connects your Medusa store to Qinto, Blotout's first-party analytics and identity platform, and sends your storefront and order events there — without an ad blocker in the way.

The package is ; the service it talks to is Qinto, which is what you will see named throughout the admin and in your Qinto dashboard.

Install it, paste your Qinto URL in the Medusa admin, mount one component in your storefront.

One line in , and everything a merchant chooses — destination, on/off — is set in the admin and stored in your database, so changing it needs no redeploy.


What you get

EventWhen
every navigation
a product page
/ cart changes
every arrival at checkout, including each step change
/ checkout steps
order confirmation page
account created

Identity (email, name, city, country, postcode, address) attaches to the shopper's profile at checkout and on the order.

Every event is sent from the browser, including , which is keyed on the order id so a refreshed confirmation page still counts once. Nothing is sent from your server, and your server holds no Qinto credential — there is no column for one.


1. Install

Add it to :

That is the whole configuration. Everything else — the destination, on/off — is set in Admin → Blotout and stored in your database.

There is no OAuth, no client secret, and no credential of any kind. The one thing this plugin needs is your site's Qinto URL, which is a public delivery host — it is already visible in the page source of any site running Qinto. You copy it from the Qinto portal and paste it in the admin. The plugin's schema has two meaningful columns, and , and no column for a token because nothing here ever holds one.

Why the line is not optional. Any plugin that ships admin UI imports . Medusa's admin bundler pre-bundles React but does not deduplicate it, so with pnpm — or any install that does not hoist — that import can resolve to a second copy of React inside the plugin. Hooks then get a null dispatcher and the page dies with , which looks like a bug in the plugin and is not. One line of fixes it. If you already set , merge the into what you have rather than replacing it.

Run the migration and start:

In production, rebuild so the admin page is bundled — picks it up automatically, a built admin does not:

No environment variables are required. Nothing calls back into the store, so a backend the internet cannot reach (a local dev store, a private network) configures like any other.


2. Connect, in the admin

The plugin appears as Blotout in the sidebar. Open it:

  1. Paste your Qinto URL and press Save. Find it in the Qinto portal under Developer tools, on your site's page.
  2. Leave Tracking on. The switch stops sending without losing the destination, so you can pause and resume without re-entering anything.
  3. The badge reads Sending events when it is ready.

Everything is stored in your database, so changing destination or turning tracking off needs no redeploy. A storefront picks the change up on its next page load; tabs already open keep the previous setting until then, and the config response is cached for 60 seconds.


3. Storefront

The backend half is done. Your storefront still has to say when a shopper viewed a product or added to cart, because only it knows — but it works that out for itself.

Install the same package in your storefront and import from it — nothing is copied, so plugin updates reach the capture logic through like any other dependency. From your storefront's root:

Let Next compile the package's TypeScript, in :

Mount one component in :

And add one three-line file, :

That one file has to exist for real. Next finds route handlers by scanning your filesystem, so a route sitting in is invisible to the router — but what it does still lives in the package and updates with it.

That is two edits to files you already had, plus one three-line file, and the last of it you will ever write for this plugin. New events ship in a package update; nothing in your product, cart or checkout code is touched, so restyling them cannot break tracking.

It reads the Qinto URL from , so there is no environment variable to set — if you would rather pin it, set and it wins.

How it captures without touching your pages

Three signals, none of which needs a call site:

  • Route changes give directly, and say when a shopper is on a product page, the checkout, or an order confirmation.
  • — the route handler you copied — runs on your storefront's own server, where the cookie is readable, and hands the browser the cart, product or order. The browser cannot read that cookie, which is why this file exists.
  • A notices when a Server Action completes. Every cart mutation in a Medusa storefront is one, so the component re-reads the cart and compares it to the previous state. The difference is the event: a line going 1 → 3 is of 2.
  • A listener on picks up identity from any form a shopper sends — register, login, and each of the profile forms — without those components being touched. A signed-in shopper is also identified from the session on page load, which covers a returning visit where no form is ever submitted.

The visitor cookie

The context route also issues — a first-party visitor id, the same mechanism the WooCommerce, Magento and Salesforce integrations use, under the same name.

ValueUUID v4, minted once and never replaced
Lifetime400 days — the real browser maximum, not the century a cookie can ask for
Flags, , on https
Scopewidened to the domain shared with your Qinto host when there is one, host-only otherwise

It exists because Qinto's own anonymous id is set by the collector, which makes it third-party until your DNS setup puts the collector on your domain. is set by your storefront's own server, so it is first-party from the first request and stable across page loads either way.

rather than on purpose: the starter's cart and auth cookies are so they survive the cross-site return from a redirect-based payment method, and a visitor id that did not would be lost at exactly the moment a conversion is attributed.

The scope is only widened when your storefront actually sits under that domain. A browser discards a cookie scoped to a domain the response did not come from, so a store at reporting to gets a host-only cookie rather than none at all.

An explicit allowlist decides what is read — the nine identity traits, each with the field names that feed it, including the names the checkout uses. The form is never enumerated and no other input is inspected, so a password or a card number in the same submission cannot be picked up by accident. Widening what is collected means editing , which is deliberate.

Deriving beats declaring in two ways beyond the edit count: and come from the authoritative cart rather than a recomputed variant price, and an event only fires for a mutation that actually succeeded.

Patching looks like the obvious way to catch those Server Actions. It does not work — Next captures its own reference while the framework boots, long before a component effect can replace the global, so the patch silently never fires. has no such ordering problem.

Route matching defaults to the Medusa Next.js starter's shapes, so , and . A storefront that moved them passes to the component, as a pattern per event or a function where a pattern will not reach. The rules live in , pure and unit-tested, and MERCHANT-SETUP.md has the reference. Only , and read the path at all, the other six come from cart and customer state and never need configuring.

Identity (email, name, city, country, postcode, address) attaches to the shopper's profile at checkout and on the order.

Every event is sent from the browser, including , which is keyed on the order id so a refreshed confirmation page still counts once. Nothing is sent from your server, and your server holds no Qinto credential — there is no column for one.


Notes worth reading before you debug

  • Cart mutations are Server Actions. Medusa's is , so nothing inside it can reach the browser runtime — which is why capture observes actions completing rather than hooking their call sites.
  • derives a Purchase's event id from . Do not override it, or a refreshed confirmation page counts the order twice.
  • Field names are exact. not ; not ; and . A wrong name is dropped silently rather than rejected.
  • This is not the EdgeTag SDK. speaks a different protocol and its call gets from Qinto. Use the files in .

Configuration reference

Everything below is optional. Plugin options win over environment variables, and anything set in the admin wins over both.

OptionEnv fallbackMeaning

| | | fallback before a site is chosen in the admin |

Nothing is encrypted at rest because nothing stored is secret: the destination is a public host and the switch is a boolean.

One thing to know about . It is a fallback, not a default: a value set here keeps applying even after you disconnect in the admin. The admin page says so when the destination is coming from configuration. To stop sending entirely, use the tracking switch, or remove the option and restart.

Troubleshooting

The admin page shows stale behaviour after upgrading the plugin. Medusa's dev server pre-bundles plugin admin extensions with Vite, and the cache key does not change when only the plugin's contents change — so the browser keeps running the previous build and can call routes that no longer exist. Clear both caches and restart:

Then hard-reload the browser. This only affects development; a production produces a fresh bundle each time.

Events are not arriving. Three things, in order: the destination in Admin → Blotout matches exactly what the Qinto portal shows; the badge reads Sending events; and your storefront's root layout mounts the component. on your backend answers the first two — it returns the URL the storefront will use, or .

Every page load looks like a new visitor. Qinto's own anonymous id is set by the collector, so it only persists when the collector is served from your domain; on a host the browser partitions it away and mints a fresh one per page load. The plugin's cookie (below) is not affected — it is set by your own server and is stable from the first request. Complete the DNS/CNAME setup in the Qinto portal so the collector is a subdomain of your store, and the two line up.

API routes

RoutePurpose
the storefront reads its Qinto URL here
connection status
set the Qinto URL, or turn tracking on and off

Three routes, and only one of them is public. returns a URL that is already public and nothing else — no token, because there is none to leak.

License

MIT

Еще в этой категории

Посмотреть все
Аналитика
Google Analytics logo

Google Analytics

От Variable Vic

Отслеживайте e-commerce события заказов и корзины

Загрузка данных
npm
Аналитика
Bloomreach logo

Bloomreach

От Igor Ludgero Miura

Отправляйте уведомления и отслеживайте вовлечённость

Загрузка данных
GitHubnpm
Аналитика
K

Klaviyo

От Oak-digital

Плагин Medusa v2 для отслеживания событий и подписок в Klaviyo.

Загрузка данных
npm
npm install @blotout/platform-medusa
1module.exports = defineConfig({
2 // …
3 admin: {
4 // Required. Without it the Blotout admin page will not render — see the note below.
5 vite: () => ({ resolve: { dedupe: ["react", "react-dom"] } }),
6 },
7 plugins: ["@blotout/platform-medusa"],
8})
1npx medusa db:migrate
2npm run dev
npx medusa build && npx medusa start
npm install @blotout/platform-medusa
1const nextConfig = {
2 transpilePackages: ["@blotout/platform-medusa"],
3 // ...the rest of your config
4}
1import QintoAutoCapture from "@blotout/platform-medusa/storefront/autocapture"
2
3<body>
4 <QintoAutoCapture />
5 <main className="relative">{props.children}</main>
6</body>
export { GET } from "@blotout/platform-medusa/storefront/context-route"
1rm -rf node_modules/.vite .medusa
2npm run dev