Shopify Integration Guide
Tajo connects Shopify to Brevo in two places. The Tajo Shopify app turns Shopify webhooks into Brevo writes as they arrive. Sync rules, which an agent builds and a person approves, move records into Brevo on a schedule. This page covers both, then the Shopify tools Tajo serves over MCP.
Prerequisites
Before starting the integration, ensure you have:
- Shopify store on any plan (Basic, Shopify, Advanced, or Plus)
- Tajo account (Tajo is in early access)
- Brevo account, the destination for the sync
- Admin access to your Shopify store
Step 1: Connect Your Shopify Store
Tajo is in early access. The Shopify app is not listed in the Shopify App Store, and there is no self-serve install link. Contact the team to get set up. Once your Tajo workspace is ready:
- In Tajo, open Connections.
- Enter your store’s myshopify.com domain and choose Connect Shopify. Shopify shows the scopes Tajo requests and returns you to Tajo when you approve them.
- Check what each scope is for, and what Tajo writes back to Shopify, in Shopify permissions explained.
Step 2: What the Tajo Shopify App Sends to Brevo
The app verifies each Shopify webhook, stores it, queues it and processes it straight away. Customer and product topics wait about four seconds first. There is no batch window. A failed job is retried with backoff.
Webhook topics
The Tajo Shopify app subscribes to these Shopify webhook topics:
| Webhook topics | Purpose |
|---|---|
customers/create, customers/update, customers/delete | Keep Brevo contacts current |
orders/create, orders/updated, orders/fulfilled, orders/cancelled | Order events and order metrics for Brevo |
orders/paid, refunds/create | Award and deduct loyalty points |
checkouts/create, checkouts/update | Abandoned checkout recovery in Brevo |
products/create, products/update, products/delete | Keep the product catalog in Brevo current |
inventory_levels/update | Keep product stock in Brevo current |
collections/create, collections/update, collections/delete | Keep collections current |
companies/*, company_contacts/*, company_locations/* (create, update, delete) | B2B company sync |
app/uninstalled, app/scopes_update, app_subscriptions/update | App lifecycle |
Shopify’s mandatory privacy webhooks (customer data request, customer redact, shop redact) are also handled. The app does not subscribe to carts/*. Abandoned carts come from the checkouts/* topics.
What lands in Brevo:
| Shopify event | In Brevo |
|---|---|
| Customer created or updated | The contact is created or updated with name, email and marketing consent. On paid plans the app adds tags, order count, amount spent and last order. |
| Customer deleted | The contact is unsubscribed, not deleted |
| Order created, updated, paid, fulfilled or cancelled | The order through Brevo’s orders API, and the events order_paid, order_completed and order_cancelled |
| Refund created | The event order_refunded. If you run a Brevo loyalty program through Tajo, points are deducted in proportion. |
| Order paid, with a Brevo loyalty program | Points awarded at your points-per-dollar rate |
| Checkout created or updated, with an email and items | The events cart_updated and cart_abandoned. Your Brevo automation decides when to send. |
| Product or collection created, updated or deleted | Brevo’s product catalog and categories |
| Inventory level updated | The product’s stock in Brevo’s catalog. When a variant goes from 0 to above 0, each shopper who asked to be notified gets a back_in_stock event, once per restock. |
The app does not add a “Notify me” button to your theme. A back-in-stock request has to come from your storefront, for example from a button you add.
Existing data
On install, the app imports your existing customers as Brevo contacts. A full historical sync is started from the app’s sync page. On paid plans it also imports products, collections, companies and orders.
Step 3: Build a Sync Rule with the Agent
A sync rule is a declarative definition of one sync: a source resource, a Brevo action, a field map and a filter. You do not write it by hand. You describe it, an agent builds it, and a person approves it.
- In Tajo, open Agents and ask the Brevo Integration Architect for the sync in plain language. For example: “Send Shopify customers who accepted email marketing to Brevo as contacts.”
- The agent inspects the Shopify connector. Its sample returns field names and types, never customer values.
- It proposes a rule with a field map and a filter, then validates the field map against Brevo’s action and dry-runs the draft. Neither step reads customer records.
- It saves the rule as a draft. You can also start from a template under Connections > Syncs and mappings > New sync from template.
- Request publish approval runs a preview against your store. It reads at most 10 records, writes nothing to Brevo and does not move the cursor. It records counts only: records pulled, eligible, mapped and rejected by the filter, plus mapping errors. If the preview fails, no approval is created.
- A person approves the request on the Approvals page, with a written rationale. The approval is bound to a SHA-256 digest of the rule and expires after 30 minutes. The rule page then shows Publish approved version.
Editing a published rule returns it to draft. It goes back through preview and approval before it runs again.
A real rule
This is the Shopify customers -> Brevo contacts template as Tajo defines it:
sourceSlug: "shopify",sourceResource: "customers",destinationSlug: "brevo",destinationAction: "upsert_contact",fieldMap: [ { source: "email", destination: "email", transform: "toLowerCase" }, { source: "first_name", destination: "attributes.FIRSTNAME" }, { source: "last_name", destination: "attributes.LASTNAME" }, { source: "phone", destination: "attributes.PHONE" }, { source: "total_spent", destination: "attributes.TOTAL_SPENT", transform: "toNumber" }, { source: "orders_count", destination: "attributes.ORDERS_COUNT", transform: "toNumber" }, { source: "tajo_email_marketing_consent", destination: "attributes.OPT_IN", transform: "toBoolean" }, { source: "tags", destination: "attributes.SHOPIFY_TAGS" }, { source: "id", destination: "attributes.SHOPIFY_ID", transform: "toString" }, { source: "created_at", destination: "attributes.SHOPIFY_CREATED_AT" }, { source: "updated_at", destination: "attributes.SHOPIFY_UPDATED_AT" },],filterExpression: "($json.tajo_email_marketing_consent === true) && ($json.tajo_email_suppressed === false)",The filter is the consent check. Tajo derives both values from Shopify’s email_marketing_consent.state, or the older accepts_marketing flag. A rule that writes contacts to Brevo cannot be published without it. The other Shopify template, Shopify orders → Brevo orders, records orders in Brevo for buyers who accepted marketing at checkout.
When a rule runs
- Contact sync rules run every 15 minutes by default. Each run starts from the rule’s cursor.
- An active rule’s page has a Test run (1 batch) button.
- An active, published Shopify orders → Brevo orders rule also runs every 15 minutes. Its first scheduled run starts a few minutes before that moment and sends no older orders. Each later run sends the orders updated since the previous one.
- Past orders reach Brevo only when you run the rule yourself: with Test run (1 batch), or by asking the Sync Operator agent to run it.
- An orders rule runs on schedule only with the template’s buyer marketing opt-in filter. A rule whose filter was edited runs only when you start it.
- After five consecutive failed runs, the rule pauses itself and its page shows the last error. Fix the cause, then publish again.
Each run is listed in the rule’s run history with records read, written and failed, and its duration.
What the Shopify Connector Reads and Writes
Sync rules only write to the destination, here Brevo. They never write to Shopify.
The Tajo Shopify app requests 12 scopes and makes a short list of writes to Shopify, such as consent opt-outs and loyalty tags. Shopify permissions explained lists every scope and every write, with what triggers it.
Agents and MCP hosts reach the store through the Shopify connector:
| Reads | Writes |
|---|---|
| Shop details, customers (list and search), orders, products, customer metafields, inventory levels, bulk export status | Customer metafields and customer tags, and starting a bulk export. Each write is staged as a proposal and runs only after it is approved. |
The connector also declares an inventory adjustment. It needs the write_inventory scope, which the Tajo Shopify app does not request.
Step 4: Use the Shopify Tools over MCP
Tajo serves the Shopify connector as an MCP server at https://alto.tajo.io/mcp/connectors/shopify. Add it to Claude Code:
claude mcp add --transport http tajo-shopify https://alto.tajo.io/mcp/connectors/shopifyThe host discovers Tajo’s OAuth server and opens the Tajo sign-in. Access is limited to early-access accounts. The server exposes 12 tools:
| Tool | What it does |
|---|---|
preview_tajo_shopify_app | Interactive preview of the Tajo Shopify app, rendered as MCP UI |
get_shop | The shop’s details |
search_customers | Search customers with Shopify query syntax, such as tag:tajo-vip or total_spent:>100 |
list_customers | List customers, paginated |
list_orders | List orders, paginated |
list_products | List products with variants, images and inventory |
get_customer_metafields | Read a customer’s metafields |
get_inventory_levels | Read a variant’s inventory across locations |
poll_bulk_export | Check a bulk export and get its download link when it completes |
calculate_rewards_profile | Calculate a customer’s tier, points and reward balance from synced commerce data |
shopify_propose | Stage one Shopify write as a proposal. Nothing is sent. |
shopify_apply | Run an approved proposal |
Troubleshooting
- Contacts not appearing in Brevo: see contacts missing in Brevo.
- A rule that does not run, or paused itself: see data not syncing.
Next Steps
- Understanding data sync, how sync rules behave
- Shopify permissions explained, every scope and every write
- Shopify + Brevo, the integration guide
- Contact the team to get set up