Indexing and sync
Why a product you just added is not in the results yet.
Marutto Search does not query Shopify directly; it keeps its own index. Three mechanisms keep that index from drifting away from the real catalogue.
1. Webhooks — immediately, on every change
Product creation, updates and deletion arrive as Shopify webhooks. This normally lands within seconds.
| Webhook | Keeps up to date |
|---|---|
products/create | New products |
products/update | Title, price, stock, tags and so on |
products/delete | Removed products |
Webhooks fire only when something changes. Anything that changed while the app was unreachable never arrives, which is what the next two mechanisms exist for.
2. Drift check — every six hours
Every six hours the index count is compared against Shopify's. If they disagree, the index is rebuilt automatically.
- No merchant action is required; it runs whether or not anyone opens the admin
- The check only counts products, so it is cheap — only a shop that has actually drifted pays for a rebuild
- The admin home shows the last sync time and the result of the comparison
Why this is needed. A full sync only runs when the merchant presses the button; between full syncs the index is maintained by webhooks, and webhooks only fire on change — so anything missed stays missed until somebody notices. In production we found one shop that had gone 49 days without a full sync, and another that had never had one.
3. Full sync
The whole catalogue is re-read when:
- The merchant presses the sync button in the admin
- The plan changes — a higher plan indexes more fields
- The drift check finds a mismatch
On a large catalogue this takes tens of seconds to a few minutes, during which searches report degraded.
What is never indexed
| Excluded | Why |
|---|---|
| Draft products | Not purchasable on the storefront |
| Unpublished products | Same |
| Archived products | Same |
A result count lower than the product count in the Shopify admin is usually this.
When degraded is set
degraded_reason | Situation |
|---|---|
sync_pending | A first sync, or a rebuild after a plan change, is running |
analyzer_mismatch | The store's language and the analyser disagree |
search_unavailable | A temporary failure in the search infrastructure |
Every new store passes through sync_pending on day one. See the FAQ entry.
The set of
degraded_reasonvalues will grow. Branch ondegraded(the boolean) and keep the reason for display and logs.
Translations
Translations sync separately. Shopify has no webhook for translations at all, so they are maintained by periodic reconciliation only (see Multilingual stores).
Next: Admin controls — changing results without writing code