Shopify Connector
Shopify connector for AACsearch — OAuth install flow, webhook-driven delta sync and product mapping. Early preview.
Status: Early preview. The Shopify connector source lives at packages/shopify-connector/ in the AACsearch monorepo. It is not yet published as a Shopify App Store listing — install is manual via a custom app or the development store.
The Shopify connector follows Template B (TypeScript server-side connector) from wiki/tasks/cms-platform-expansion.md. It uses Shopify's OAuth flow to obtain a per-shop access token, encrypts that token at rest, and reacts to product webhooks to push delta syncs into AACsearch.
Supported scope
- Shopify online stores (Basic, Shopify, Advanced plans).
- Products, variants, collections and inventory levels.
- Multi-currency catalogs via Shopify Markets — exported as alternative prices in
attributes.price_by_currency. - Locales configured under Shopify Markets — exported as separate documents per locale.
Headless Shopify (Hydrogen / Storefront API) is supported but requires manual sync from your own storefront server using the Custom Connector approach.
Architecture
The connector runs as a Node.js service alongside the AACsearch monorepo. The router is mounted under /api/connectors/shopify:
Shopify storefront
│ (admin install + webhooks)
▼
packages/shopify-connector/src/router.ts
├── /oauth/install ← initiates OAuth flow
├── /oauth/callback ← receives auth code, stores encrypted token
├── /webhooks/products/* ← product create/update/delete
├── /webhooks/inventory/* ← inventory level changes
└── /sync/full ← manual full resync trigger
│
▼
AACsearch Connector APIFiles of interest:
packages/shopify-connector/src/oauth.ts— Shopify OAuth 2.0 flowpackages/shopify-connector/src/crypto.ts— AES-256-GCM token encryptionpackages/shopify-connector/src/product-mapper.ts— Shopify entity →SyncProductInputpackages/shopify-connector/src/webhooks.ts— HMAC verification + debouncepackages/shopify-connector/src/sync.ts— full and delta sync drivers
Installation (current preview)
The public Shopify App Store listing is part of the v0.7 roadmap. Until then, install via a custom app on your Shopify store:
- In your Shopify admin, open Settings → Apps and sales channels → Develop apps → Create an app.
- Configure Admin API access scopes:
read_products,read_inventory,read_collections,read_locations. - Install the app and copy the Admin API access token.
- In your AACsearch dashboard, create a connector token (Connectors → New Connector Token) bound to the index you want products indexed into.
- Add a
.enventry on the AACsearch server pointing the Shopify connector at your store:
SHOPIFY_SHOP_DOMAIN=mystore.myshopify.com
SHOPIFY_ADMIN_ACCESS_TOKEN=shpat_xxxxxxxx
AACSEARCH_CONNECTOR_TOKEN=ss_connector_xxxxxxxx
AACSEARCH_PROJECT_ID=org_xxxxxxxx- Register webhooks from the Shopify admin or via API:
| Topic | Address |
|---|---|
products/create | https://your-aacsearch.example.com/api/connectors/shopify/webhooks/products/create |
products/update | https://your-aacsearch.example.com/api/connectors/shopify/webhooks/products/update |
products/delete | https://your-aacsearch.example.com/api/connectors/shopify/webhooks/products/delete |
inventory_levels/update | https://your-aacsearch.example.com/api/connectors/shopify/webhooks/inventory/update |
- Trigger an initial full sync from the AACsearch dashboard or via:
curl -X POST https://your-aacsearch.example.com/api/connectors/shopify/sync/full \
-H "Authorization: Bearer $AACSEARCH_CONNECTOR_TOKEN"Field mapping
The Shopify product → AACsearch document mapping is implemented in packages/shopify-connector/src/product-mapper.ts. Highlights:
| Shopify field | AACsearch field | Notes |
|---|---|---|
id | external_id | Numeric Shopify product ID, stable |
title | title | Localized title for the configured market locale |
body_html | description | HTML stripped before send |
vendor | brand | Empty string is dropped |
product_type + tags | categories | Plus collections that contain the product |
tags | tags | Comma-split, trimmed |
Variant sku | sku | First variant's SKU |
Variant price | price | Lowest variant price across the product |
Variant compare_at_price | sale_price | Highest "list" price across variants, when present |
variants[].inventory_quantity sum | stock_quantity | Across all locations |
| Inventory level > 0 | availability | in_stock, out_of_stock, or preorder per variant policy |
images[0].src | image_url | First image; full image list lives in attributes.images |
| Variant options | attributes.option_* | Color, size, material as facetable fields |
| Locale (Shopify Markets) | locale | One document per locale, suffixed external_id |
Variant-level documents are not exported by default — Shopify products are sent as a single document with variant data flattened into attributes. If your storefront needs per-variant search, build a custom connector that emits one document per variant.
Webhook reliability
Shopify retries webhooks up to 19 times over 48 hours on non-2xx responses. The connector returns 200 as soon as the payload passes HMAC verification and is queued for processing — the actual call into the AACsearch Connector API runs asynchronously. If the AACsearch ingest queue is unavailable, the webhook handler logs the failure and a periodic reconciliation job will reissue the delta sync on the next scheduled run.
Failed HMAC verification returns 401 immediately — Shopify will mark the webhook as failed and back off. This is the desired behavior since a verification failure means the webhook was tampered with or the shared secret rotated without the connector being updated.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Webhooks not arriving | Wrong webhook URL or HTTPS misconfigured | Re-register webhooks; verify the AACsearch host has a valid TLS cert |
401 webhook_signature_mismatch in logs | Shopify webhook secret out of sync | Rotate the webhook secret in Shopify admin; update SHOPIFY_WEBHOOK_SECRET env var |
| Full sync hangs at 1000 products | Connector batch size hit; retry logic stuck | Check Shopify Admin API rate limit headers; lower batch size to 250 |
| Products visible in Shopify, missing in search | Product not published to the "Online Store" sales channel | Publish the product to a sales channel the connector reads |
| Inventory shows 0 in search but in stock | Inventory location not whitelisted | Enable the location in connector config or add read_locations scope |
403 invalid_or_revoked_key | AACsearch connector token revoked or wrong organization | Generate a new token in the AACsearch dashboard and update AACSEARCH_CONNECTOR_TOKEN |
Roadmap
The current preview covers the OAuth flow, product/inventory webhooks, full and delta sync. Planned for the public listing release:
- One-click install from the Shopify App Store
- Per-market locale and currency UI in the embedded admin
- Variant-level documents as an opt-in mapper
- Bulk operations API for catalogs > 100k SKUs (instead of the REST batch loop)
Track the implementation under wiki/tasks/cms-platform-expansion.md § A12.
Related pages
- Connectors Overview
- Connector API Lifecycle
- Custom Connector — for headless Shopify (Hydrogen)
- Diagnostics