Shopify
The Captain Search app puts Captain’s ranking behind your Shopify theme’s own search box, and shows you how much revenue search brings in.
Quick start
How it works
The integration has two parts:
- The store connection imports your products and orders into Captain and keeps them in sync. It only reads your catalog and orders.
- The Captain Search app embed runs in your theme. It sends storefront searches to Captain and shows Captain’s results in the theme’s own search box, dropdown and search page. It adds no search box or popup of its own.
With the shopper’s analytics consent, the embed also carries an anonymous token from search to cart. An order counts as assisted by search when that shopper clicked the same product variant in Captain’s results in the 24 hours before buying.
Install and connect
Install the Captain Search app from Shopify, approve it, then sign in to Captain and link the store. The first import starts on its own.
You’ll need: a Shopify store on the Online Store sales channel, an invitation to install Captain Search, and a Captain Product Search tenant.
Before you start
- A Shopify store on the Online Store sales channel.
- A Captain Product Search tenant with the Shopify integration switched on. Captain switches it on per tenant.
- An invitation to install the Captain Search app on the store. Ask the Captain team on Slack or by email.
- Shopify staff permission to approve app installs and edit the theme.
- An owner of your Captain organization, to create the storefront key later. You can also create that key through the API, on a server, with a write key for every index or the admin key.
Connect the store
The install starts on Shopify and uses Shopify’s standard app approval (OAuth). Captain never asks for your store’s address, a Shopify password or an access token.
Start the install
Open Shopify’s install screen for Captain Search in one of two ways:
- From the Captain console: open Developers, then Integrations. On the Shopify card, select Connect, then Install from Shopify.
- From Shopify: open the install link the Captain team sent with your invitation.
Approve the app in Shopify
If you manage more than one store, choose the store. Review the permissions and select Install.
Sign in to Captain
Shopify sends you to the Captain console. If you’re not signed in, sign in to the Captain organization that should own the store. The panel names the store Shopify approved.
Name the connection and catalog
In Name, enter a name for the connection, such as the store’s name. In New catalog name, keep shopify-products or enter a name no other catalog uses. You’ll paste this exact name into the storefront key and the theme setting later.
The approval waits 15 minutes for you to link it. After that, install again from Shopify.
Captain Search isn’t an embedded app. Opening it from your Shopify admin takes you to the Captain console, where you manage the connection, storefront search and analytics.
The first sync starts on its own. The connection shows its status, product count and last sync in the console.
Each new connection creates a new catalog. Captain refuses a name that an existing catalog already has.
Next: turn on storefront search.
Permissions
The app asks for exactly these seven permissions. It doesn’t ask for customer records (read_customers), and it asks for no write access to products, orders or themes.
Order access is protected customer data in Shopify. Captain requests order data without names, email addresses, postal addresses or phone numbers.
Turn on storefront search
Create a public storefront key, paste it into the Captain Search app embed, and save the theme.
You’ll need: a connected store (see Install and connect), the catalog name, and either an owner of your Captain organization or a server with a write key.
Search on the storefront changes only after the app embed is on and saved in the live theme.
Create a storefront key
The key in the theme is public. Anyone can read it from the page source, so it has to be a scoped key, limited to the store’s catalog and the storefront’s addresses. A scoped key can search and send events, including purchases, for its catalog. It can’t read analytics or change records.
From the console
Open the Shopify connection’s Manage panel. Under Storefront search, select Create storefront key, and 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.
From the API
On a server, use a write key for every index ("indexes": ["*"]) or the admin key:
indexesholds the catalog the store connection created.allowed_originslists every address the storefront runs on: themyshopify.comdomain and any custom domain.- The response holds the key once. Copy it straight into the app embed below.
Turn on the app embed
Open the theme editor
In Shopify admin, open Online Store, then Themes. On the live theme, select Customize.
Fill in the settings
- Captain search endpoint: your tenant URL, for example
https://acme.captain.dev. Use the HTTPS address only, with no path. - Product index: the catalog name.
- Public scoped key: the storefront key.
- Wait for Captain up to: leave it at 400 ms.
- Product item selector (advanced): leave it empty. See Which themes work.
Settings and privacy explains each setting.
What shoppers see
The embed adds no search box, popup or branding. Shoppers use the theme’s own search. Captain decides which products appear and in what order.
-
Search dropdown. As the shopper types, the theme’s suggestions dropdown lists the products Captain ranks highest, in Captain’s order, in the theme’s own style. Query suggestions, collections and pages in the dropdown still come from Shopify.
-
Search results page. Pressing Enter opens the theme’s
/searchpage. Its product grid shows Captain’s results, in Captain’s order, as the theme’s own product cards. The result count on the page and in the browser tab is Captain’s. -
Filters, sorting and pages. On the search page, these use Captain’s results, count and order:
- filters for price, availability, vendor, product type, tag and product options;
- sorting by price, title and date;
- page 2 and later.
The page reaches Captain’s first 240 products for a search. A few choices keep the whole page on Shopify’s own results: sorting by best selling, metafield filters, and a price filter when the storefront shows a currency other than the store’s.
-
Keyboard and mobile. Arrow keys, Enter, Escape and the mobile search panel work exactly as the theme defines them. Keys pressed before the dropdown appears are held and replayed once it shows, so Arrow Down then Enter opens the highlighted product.
-
Prices in the dropdown follow the theme’s own setting. In Dawn it’s Theme settings, then Search behavior, then Show product price. When the theme hides prices in the dropdown, Captain’s rows hide them too. Product cards on the search page show prices as the theme does.
-
When Captain is slow or down, the theme shows Shopify’s own results instead. In the dropdown, Captain has 400 ms from each keystroke’s request (the Wait for Captain up to setting). On the search page it has 1.5 seconds, or three times that setting if that’s longer. An error from Captain falls back the same way, so search keeps working when Captain is down.
The embed changes only the theme’s search. Shopify search everywhere else, such as the Storefront API, other apps and other sales channels, stays as it is.
Which themes work
Dawn, Horizon and vintage themes such as Debut
The embed finds the theme’s own search form, dropdown and results, with no theme-specific setup. Captain has checked Dawn, Horizon and Debut on a live store. If predictive search is turned off in the theme, there’s no dropdown to fill, but the /search page still shows Captain’s results.
Other themes
Other themes work when they use Shopify’s standard search addresses (/search and the predictive search dropdown). If a theme still shows Shopify’s results, enter a CSS selector for one product item in its dropdown and search page, such as .product-item, in Product item selector (advanced). The Captain team can check a theme before launch.
Other languages and markets
On a translated storefront, such as /fr/, results link to the product pages in the shopper’s language, and prices on the search page follow the language’s format. Product titles in Captain’s results come from the catalog, in the store’s default language. In another market’s currency, prices come from Shopify in that currency.
Each published theme
Turn on the Captain Search app embed in every theme you publish. App embeds are set per theme.
What syncs
Captain imports your published products and the order data it needs to measure search revenue, and keeps both in sync.
You’ll need: a connected store. Nothing else to set up. Sync runs on its own.
Products
Captain indexes a product only when both of these are true:
- Its status is Active.
- It’s published to the Online Store sales channel, with a publish date that has already passed.
Draft, archived and unpublished products stay 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.
What each record holds
Each variant is one record. Search groups variants by product.
- From the product: title, description, vendor, type, tags, collections, images and handle.
- From the variant: title, options, SKU, barcode, price, compare-at price, stock and availability.
How sync runs
- First 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 you chose when connecting (6 hours unless you changed it). 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.
Orders
Captain keeps the minimum it needs to measure search revenue. For each order that counts, Captain records one purchase event with:
- the variant IDs, quantities and prices after discounts
- Shopify’s order subtotal, in the store’s 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 isn’t linked to search. Captain stores no customer names, email addresses, postal addresses, phone numbers or customer IDs.
From the Captain web pixel, Captain also records each add to cart by a consenting shopper: the variant, quantity, price and the anonymous token. For a completed checkout it keeps only a hash of the checkout token, to match express checkout orders.
Test, cancelled and refunded orders
Captain drops test orders, and orders already cancelled when it reads them, so they count zero revenue.
When an order changes after Captain records it, Captain counts what the shopper still paid for:
- A cancellation or a full refund removes the order from revenue.
- A partial refund lowers the order to the lines kept.
- An edit, for example with an item removed, restates the order at what it’s worth now.
The first import counts each order at its current value, so an order refunded before the store connected counts only what’s left.
Orders in other currencies
An order placed in another market’s currency, such as Canadian dollars on a US store, counts in the store’s currency. Captain uses Shopify’s own conversion for that order (its shop amount), so revenue never mixes currencies.
Prices that include tax
On stores whose prices include tax, Shopify’s subtotal includes that tax, so the revenue Captain records does too.
Order history
The first import reads the last 60 days of orders. Each Shopify connection shows how far back its orders go and why. Importing up to 365 days needs Shopify’s approval for read_all_orders, which Captain hasn’t received yet.
Analytics and attribution
Captain credits an order to search when a consenting shopper clicked the same product variant in Captain’s results in the 24 hours before buying.
You’ll need: the app embed turned on (see Turn on storefront search) and Shopify’s consent banner turned on.
Search works for every shopper. Analytics depend on the shopper’s consent, which the embed reads through Shopify’s Customer Privacy API.
How consent works
- 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 it’s explicit. Both Shopify’s analytics processing check and the shopper’s recorded analytics choice must say yes. A shopper who hasn’t answered the consent banner counts as not consenting. The app never grants consent for the shopper.
- 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 attributecaptain_user_token. Searches, clicks and the resulting order share that token. - When the shopper revokes consent, the embed deletes the token from the browser and clears the cart attribute. Later searches carry no identity again. Revoking stops new data. It doesn’t delete searches, clicks or orders Captain already holds.
The token isn’t tied to a Shopify customer account or email address. Captain doesn’t use customer IDs for attribution.
The Captain web pixel
Captain installs a Shopify web pixel on your store when it connects. A store connected earlier gets it on its next sync. You don’t set anything up.
Shopify runs the pixel only for shoppers who allowed analytics, or where the store needs no consent. It reports three things to Captain:
- Add to cart. Captain records every add. An add counts toward search when the shopper reached that product from a Captain result in the 24 hours before.
- Completed checkout. This links express checkout orders to search (see below).
- Page views. Captain counts each browser that allowed analytics once per day, to measure store conversion.
What Captain measures
- Searches, clicks on search results, add-to-cart and orders.
- From orders: revenue, order count and average order value.
- Store conversion: orders from shoppers who allowed analytics, divided by the distinct browsers that allowed analytics and viewed a page, per UTC day. The connection’s API and the console show it over 30 days.
Store conversion
Captain measures it with the web pixel, so it needs no extra Shopify permission.
- Shoppers who declined analytics are in neither number. In a store that asks for consent, it covers only shoppers who allowed analytics.
- It isn’t the same number as Shopify’s own conversion rate, which counts every session.
- It counts from the day the pixel was installed. There’s no history before that.
Express and accelerated checkout
Buy it now, Shop Pay and similar buttons skip the cart, so the order carries no token. The pixel’s checkout report supplies it instead. Captain accepts it only when the report’s checkout matches the order in Shopify’s signed order notification. Captain keeps only a hash of the checkout token.
The order and the report can arrive in either order. If the order comes first, Captain counts it without attribution, then credits it to search when the report arrives. An order is credited only if the shopper allowed analytics.
For the order data Captain keeps, see What syncs. For privacy requests, see Settings and privacy.
Settings and privacy
This section lists every setting, explains how to keep the storefront key safe, and covers what happens to your data when you disconnect or a privacy request arrives.
You’ll need: access to the theme editor for the app embed settings, and the Captain console for the connection.
App embed settings
Find these in the Shopify theme editor, under App embeds, then Captain Search.
If the endpoint, the index or the key is missing or invalid, the embed stays off and the theme keeps Shopify’s own search.
Connection settings
Find these in the Captain console, under Developers, then Integrations, on the Shopify connection.
- Sync every: how often Captain re-reads the whole catalog. You choose 1, 6, 12 or 24 hours when you connect.
- Sync now: starts a sync at any time.
- Manage: shows the connection’s status and creates the storefront key.
- Disconnect: stops syncing and uninstalls the Captain Search app from the store, which removes Captain’s access. The catalog stays in Captain until you delete it.
Keep keys safe
- 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 storefront key to the store’s catalog 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.
Rotate the storefront key
Disconnect or uninstall
- Disconnect in the Captain console stops syncing and uninstalls the Captain Search app from the store, which removes Captain’s access. The catalog stays in Captain until you delete it.
- Uninstall the app in Shopify also stops the connection. Shopify revokes Captain’s access, and Captain deletes its stored copy of the token within minutes. The catalog stays.
About 48 hours after an uninstall, Shopify asks Captain to delete the store’s data. See below.
Shopify privacy requests
Captain receives Shopify’s three mandatory privacy requests. It checks each request’s signature, refuses any that fail, and logs the rest.
Store data deletion (shop/redact)
Shopify sends this about 48 hours after an uninstall. Captain deletes the connection and everything it keeps about it: the sync history, the product map, queued updates and the stored Shopify access. The catalog is your Captain catalog, and it stays until you delete it. If the store has connected again since the uninstall, Captain keeps that new connection.
Customer data deletion (customers/redact)
Captain keeps no customer record. It deletes its record of the orders named in the request and any queued updates for them.
When the catalog’s engine can delete events, Captain also deletes those orders’ purchase events. While the store is still connected, Captain reads each order’s anonymous token from Shopify. For a shopper who consented to analytics, it then deletes everything under that token, including their searches, clicks and other orders. After an uninstall, Captain can’t read the token, so it deletes only the events recorded under the order number.
On an engine that can’t delete events yet, the events stay. Contact the Captain team on Slack to have them removed.
Customer data request (customers/data_request)
Captain logs the request, and the Captain team answers it by hand.
Questions about a request? Contact the Captain team on Slack.
Troubleshooting and good to know
Find your symptom below, then check the limits of the beta under Good to know.
You’ll need: a private browser window for testing, and the browser’s developer tools for a few checks.
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 you made them in.
- Check that Captain Search is turned on in the live theme.
- Check that its settings are filled in and the theme is saved.
- Test in a private window.
Search shows the store's usual results instead of Captain's
The theme falls back to Shopify’s results when Captain fails or is too slow.
To see which results are showing, open the browser’s developer tools. Captain’s results carry the attribute data-captain-results on the dropdown’s product list (#predictive-search-results-products-list) and on the search page’s grid (#product-grid). Then check the request to /v1/indexes/{index}/search:
403means the key doesn’t allow this storefront address or this catalog. Add every storefront address to the key’sallowed_origins, including a custom domain, and check that the key’s catalog matches Product index.401means 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, and the theme keeps Shopify’s own search. If the theme still shows Shopify’s results, set Product item selector (advanced) (see Which themes work).
- The endpoint must be an HTTPS address with no path.
- The catalog name may contain only letters, digits,
-and_. - The key must not be empty.
A product is missing from results
Check that the product is Active, 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 aren't attributed
Attribution needs the shopper’s analytics consent. Check that the store’s consent banner is on and that your test shopper accepted analytics. For express checkout orders, the credit can appear a little after the order, once the pixel’s checkout report arrives.
Good to know
- The app is in beta and not in the Shopify App Store. Captain installs it store by store.
- On the search page, sorting by best selling, metafield filters, and a price filter in a currency other than the store’s show Shopify’s own results.
- The search page reaches Captain’s first 240 products for a search.
- Captain’s product cards on the search page link to the product and leave out the theme’s quick-add button.
- The result count and the no-results message the embed writes follow the storefront’s language, in 31 languages. Only English has been shown on a live store so far.
- When the storefront shows a different currency from the catalog’s, the embed hides Captain’s prices rather than show the wrong currency.
- The first import reads the last 60 days of orders. Each Shopify connection shows how far back its orders go and why. Importing up to 365 days needs Shopify’s approval for
read_all_orders, which Captain hasn’t received yet. - A cancellation or refund of an order recorded before 20 October 2026 is subtracted only when that shopper didn’t allow analytics. Otherwise the order keeps its original value.
- Captain answers Shopify customer data requests by hand.