Start here
How it works
Shopify → indexer → Typesense → widgets, end to end.
Four stages, in this order. Everything else in these docs is a detail of one of them.
1. Ingest#
On install — and on every full reindex after that — the app runs a Shopify GraphQL bulk operation that pulls your entire catalog: products, variants, SKUs, prices, compare-at prices, inventory levels, vendor, product type, collection memberships and metafields.
Nothing is copied into a WySync product table. Shopify remains the source of truth for your catalog; we hold only the derived search documents plus your app configuration.
On Growth and above the app also subscribes to products/create, products/update, products/delete and inventory_levels/update webhooks, so individual changes flow through within seconds instead of waiting for the next scheduled run.
2. Resolve#
Each product's fitment is computed by merging every source you've connected:
- product tags matching the
fits_…grammar - CSV uploads and Google Sheets rows, expanded across year ranges
- metafield specs, canonicalised (lengths, diameters, positions — and bolt patterns and offsets where you sell wheels)
- vendor feed rows for the SKUs the supplier recognises
- fitment editor overlays — your manual additions, exclusions, universal flags and notes
The merge is a union: if any source confirms a SKU fits a vehicle, it fits. There is no precedence order to configure and no "winning" source, because in practice every source is incomplete in a different direction.
Editor overlays are the exception, and deliberately so — they are applied after the union, which is what makes an exclusion able to remove a fit a supplier feed wrongly claims.
3. Index#
The resolved documents are written into a Typesense collection named for your shop. That index carries the fitment vehicle IDs, the typed spec fields used for facets, a stock tier, and the ranking inputs.
A Redis layer sits in front of the hot read paths — collection queries, search, suggestions — keyed by shop, so a popular vehicle's collection page is usually served without touching the search engine at all.
A shopper's page never waits on Shopify's Admin API for a fitment answer. Fitment filtering is an intersection inside the index, which is why turning it on doesn't slow a collection page down the way a Liquid loop over tags would.
4. Serve#
The nine widgets are Liquid blocks plus vanilla JavaScript — no framework in your storefront. They talk to the app through Shopify's app proxy, so requests go out from your own domain (/apps/wysync/api/…) and arrive HMAC-signed. They never call Shopify and never call our database directly.
All nine read the same vehicle state, held in the browser and synced to the customer's account when they're logged in. Changing the vehicle in the persistent bar changes the answer on the product page, the cart and the next collection page, without a reload for the components already on screen.
What happens when something is down#
The ladder is deliberate and visible:
- Retry the search index.
- Show an honest "indexing in progress" state rather than an empty grid.
- Fall back to Shopify GraphQL directly — slow, but correct — as a last resort.
A missing fitment answer degrades to unconfirmed, never to a false fits. That rule is worth more than any amount of uptime.
Support is answered by the people who wrote this code — not a ticket queue.