Skip to navigation

Shopify

The Shopify integration is in beta. Captain installs it for each store by invitation. It is not listed in the Shopify App Store.

The Captain Search app connects a Shopify store to a Product Search index. Captain imports the store’s published products, keeps them in sync, and answers the storefront’s search box from that index. With the shopper’s analytics consent, the embed also carries an anonymous token from search to cart. An order then counts as assisted by search when that shopper clicked the same product variant in Captain’s results in the 24 hours before buying.

The integration has two parts:

  • The store connection imports products and orders into Captain. It is read only for catalog and order data.
  • The Captain Search app embed runs in the store’s theme. It sends storefront searches to Captain and shows the results.

Requirements

  • A Shopify store on the Online Store sales channel.
  • A Captain Product Search tenant with the Shopify integration enabled. Captain enables it per tenant.
  • An invitation to install the Captain Search app on the store. Ask the Captain team on Slack or email.
  • Shopify staff permission to approve app installs and edit the theme.
  • An owner of the Captain organization, to create the storefront’s browser key in the console. Alternatively, create it through the API on a server, with a write key for every index or the admin key.

Connect the store

The connection runs through Shopify’s standard app approval (OAuth). Captain never asks for a Shopify password or an access token.

  1. In the Captain console, open Developers, then Integrations.
  2. On the Shopify card, select Connect.
  3. In Name, enter a name for the connection, for example the store’s name.
  4. In New catalog name, keep shopify-products or enter another name no other catalog uses. This exact name goes into the browser key and the theme setting later.
  5. In Sync every, choose how often Captain re-reads the whole catalog: 1, 6, 12 or 24 hours. The default is 6 hours.
  6. In Store domain, enter the store’s myshopify.com address, for example your-store.myshopify.com.
  7. Select Connect with Shopify.
  8. In Shopify, review the permissions and approve the install.
  9. Wait for Shopify to return to the Captain console. A green message reads “Shopify is connected. Your first import starts in a few minutes.”

Each new connection creates a new catalog. Captain refuses a name an existing catalog already has.

The first sync starts on its own. The connection shows its status, product count and last sync in the console.

Permissions

The app requests exactly these seven permissions. It asks for no access to customer records (read_customers) and for no write access to products, orders or themes.

PermissionWhy Captain needs it
read_productsImport products and variants, and receive product create, update and delete notifications.
read_inventoryStore stock levels and availability with each variant.
read_ordersMeasure revenue from search. Captain reads new orders and up to the last 60 days of order history.
read_publicationsReserved. The current release checks Online Store publication from each product’s publish date.
read_themesReserved for theme setup checks. The current release does not read themes.
write_pixelsReserved for a Captain web pixel. The current release installs no pixel. This is the only write permission requested.
read_customer_eventsReserved for reading that pixel’s events. The current release reads no customer events.

Order access is protected customer data in Shopify. Captain requests order data without names, email addresses, postal addresses or phone numbers.

Enable search in the theme

Search changes on the storefront only after the app embed is turned on and saved in the live theme.

Create a browser key

The key in the theme is public: anyone can read it from the page source. Use a scoped key limited to the store’s index and the storefront’s address. A scoped key can search and send events, including purchases, for its index. It cannot read analytics or change records.

The quickest way is the console. Open the Shopify connection’s Manage panel and, under Storefront search, select Create storefront key. Add the store’s own domains if it has any. The panel shows the endpoint, the catalog and the key once, ready to paste. Only an owner of the organization can create the key.

To create it through the API instead, use a write key for every index ("indexes": ["*"]) or the admin key, on a server:

curl -X POST "https://acme.captain.dev/v1/keys" \
-H "Authorization: Bearer $CAPTAIN_WRITE_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "scoped",
"indexes": ["shopify-products"],
"allowed_origins": ["https://your-store.myshopify.com", "https://www.your-store.com"],
"description": "Shopify storefront search"
}'
  • indexes holds the catalog the store connection created.
  • allowed_origins lists every address the storefront is served from: the myshopify.com domain and any custom domain.
  • The response holds the key once. Copy it straight into the theme setting below.

Turn on the app embed

  1. In Shopify admin, open Online Store, then Themes.
  2. On the live theme, select Customize.
  3. Open App embeds in the theme editor sidebar.
  4. Turn on Captain Search.
  5. In Captain search endpoint, enter the tenant URL, for example https://acme.captain.dev. Use the HTTPS address only, with no path.
  6. In Product index, enter the catalog name.
  7. In Public scoped key, paste the browser key.
  8. Select Save.
  9. Open the storefront in a new private window and search for a product.

Once enabled, the embed handles both typing in the theme’s search box and submitting the search form. Results open in an accessible dialog with links to each product variant. The theme’s built-in predictive search is turned off while the embed is on.

What gets indexed

Captain indexes a product only when both of these are true:

  • Its status is Active.
  • It is published to the Online Store sales channel, with a publish date that has already passed.

Draft, archived and unpublished products are left out. A product scheduled for a future date appears after that date, on the next sync. When a product changes to draft, archived or unpublished, or is deleted, Captain removes it from search when it processes Shopify’s notification, usually within minutes. If a notification is missed, the next successful scheduled resync removes it.

Each variant is one record. Search groups variants by product. A record holds the product’s title, description, vendor, type, tags, collections, images and handle, and the variant’s title, options, SKU, barcode, price, compare-at price, stock and availability.

How sync works

  • Initial import. After the store connects, Captain exports the full catalog from Shopify in bulk and builds the index. Large catalogs take a few minutes.
  • Live updates. Captain subscribes to Shopify’s product create, update and delete notifications. Each one updates the matching records in the background.
  • Scheduled resync. Captain re-reads the whole catalog at the interval chosen when connecting (6 hours unless changed). This catches anything a notification missed.
  • Manual sync. Sync now on the connection starts a sync at any time.

Captain checks the signature on every Shopify notification and ignores any that fail.

Search works for every shopper. Analytics depend on the shopper’s consent, read through Shopify’s Customer Privacy API.

  • Before consent, the embed sends searches with no identity, and those searches stay out of the search log. It records no clicks.
  • Consent counts only when explicit. Both Shopify’s analytics processing check and the shopper’s recorded analytics choice must say yes. A shopper who has not answered the consent banner is treated as not consenting. The app never grants consent on the shopper’s behalf.
  • After consent, the embed creates a random anonymous token (captain- followed by a random UUID). It keeps the token in the browser’s local storage and writes it to the cart attribute captain_user_token. Searches, clicks and the resulting order share that token.
  • When consent is revoked, the embed deletes the token from the browser and clears the cart attribute. Later searches carry no identity again. Revoking consent stops new data. It does not delete searches, clicks or orders Captain already holds.
  • If the store shows no consent banner, no shopper consents, so Captain records no searches, clicks or attributed orders. Turn on Shopify’s consent banner to measure search revenue.

Captain answers Shopify customer data and redaction requests by hand today. Contact the Captain team on Slack.

The token is not tied to a Shopify customer account, email address or checkout. Captain does not use customer IDs or checkout tokens for attribution.

Order data

Captain keeps the minimum needed to measure search revenue. For each order that counts, Captain records one purchase event:

  • the variant IDs, quantities and prices after discounts
  • Shopify’s order subtotal and currency
  • the order time
  • the anonymous captain_user_token, when the order has one

An order without a token is recorded under its Shopify order ID and is not linked to search. Captain stores no customer names, email addresses, postal addresses, phone numbers or customer IDs.

Captain drops test orders, and orders already cancelled when it reads them, so they count zero revenue. A later cancellation or refund is not subtracted yet. On stores whose prices include tax, Shopify’s subtotal includes that tax.

Security

  • Never put a write key, an admin key or a search key in a theme. A search key can read analytics, including what shoppers search for. Use a scoped key only.
  • Restrict the browser key to the store’s index and storefront addresses. A request from any other site gets 403 ORIGIN_NOT_ALLOWED.
  • Never put a Shopify access token, API secret or staff credential in a theme setting.
  • To rotate the browser key, create the new key, paste it into the app embed and save, then revoke the old key with DELETE /v1/keys/{key_id}, using a write key for every index or the admin key.
  • Disconnecting the store in the Captain console stops syncing and removes Captain’s access. The catalog stays in Captain until it is deleted. Uninstalling the app in Shopify also stops the connection.

Troubleshooting

Search works in the theme editor but not on the live store. Theme editor changes apply only after Save, and only to the theme they were made in. Check that Captain Search is turned on in the live theme, that its settings are filled in, and that the theme was saved. Test in a private window.

Search shows “Search is temporarily unavailable.” Captain refused or failed the request. Open the browser’s developer tools and check the request to /v1/indexes/{index}/search.

  • 403 means the key does not allow this storefront address or this index. Add every storefront address to the key’s allowed_origins, including a custom domain, and check that the key’s index matches Product index.
  • 401 means the key is wrong, revoked or expired. Create a new scoped key and save it in the app embed.

Nothing changes on the storefront. The embed stays off when a setting is missing or invalid. The endpoint must be an HTTPS address with no path, the index name may contain only letters, digits, - and _, and the key must not be empty.

A product is missing from results. Check that the product is Active and published to the Online Store sales channel, and that its publish date has passed. Then run Sync now on the connection and search again after it finishes.

A deleted or unpublished product still appears. Run Sync now. The next successful scheduled resync also removes it. If the connection shows Failing, fix the error it names first.

Clicks or orders are not attributed. Attribution needs the shopper’s analytics consent. Check that the store’s consent banner is on and that the test shopper accepted analytics. Orders from accelerated checkout are not attributed yet (see below).

Current limitations

  • Beta, by invitation. The app is not in the Shopify App Store. Captain installs it per store.
  • Cancellations after the order. A cancellation or refund after Captain records an order is not subtracted yet.
  • No add-to-cart tracking. Captain records searches, clicks and orders, not add-to-cart events.
  • No accelerated checkout attribution. Orders placed through express or accelerated checkout buttons may skip the cart, so they carry no token and are not linked to search.
  • No fallback to Shopify search. When Captain cannot answer, the dialog shows an error instead of Shopify’s own results.
  • The theme’s search results page is unchanged. The embed answers the search box and search form. Opening the store’s /search page directly still shows the theme’s own results.
  • Theme compatibility. The embed works with themes that use Shopify’s standard search form and predictive search. Themes with custom search scripts may need a check before launch.
  • Conversion rate is not measured. Captain reports revenue, order count and average order value from orders. Visitor conversion rate needs store session counts, which the app does not request.
  • Order history. The initial import reads up to the last 60 days of orders.