Storefront triggers
Every other trigger in this app starts from something that happened in your admin: an order was paid, a product was updated, a metafield changed. Shopify tells us, and your workflow runs.
Storefront triggers start from something a shopper did. A product page was viewed, an item was added to the cart, a search returned nothing, a discount code was rejected at checkout. Shopify does not send webhooks for any of that, so the app collects it with a Web Pixel that runs on your storefront.
That difference is worth holding on to, because it explains most of what follows: what the app can see, what it cannot, and why these triggers can be far higher volume than the ones you are used to.
The Storefront Pixel
When your first storefront trigger is switched on, the app installs a Web Pixel on your storefront automatically. There is no theme edit and no code to paste.
The pixel only subscribes to the events your enabled triggers need. If you enable Storefront Search and nothing else, product views are never sent, never received and never counted. Switching every storefront trigger off again leaves the pixel installed but idle: it subscribes to no events and sends nothing.
Shopper consent
The pixel respects your store's customer privacy settings. It needs analytics consent, and Shopify only runs it for a shopper who has given that consent. Without it nothing is collected in the browser, nothing reaches us, no allowance is used and no workflow runs.
This applies at checkout too, so Checkout Error Shown and Checkout Discount Code Rejected need the same consent as the storefront triggers.
It also means storefront triggers under-report by design in regions where consent is opt-in. That is the correct behaviour, not a bug to work around.
window.Shopify.loadFeatures(
[{ name: "consent-tracking-api", version: "0.1" }],
(error) => {
if (error) return;
// Call this when the shopper makes a choice in your banner.
// Pass what they actually chose - storefront triggers need analytics.
window.Shopify.customerPrivacy.setTrackingConsent(
{ analytics: true, marketing: false, preferences: false },
() => {},
);
},
);Shopify's reference for this is the Customer Privacy API.
When you test a storefront trigger, accept the cookie banner first and use a browser without an ad blocker. A private window starts without consent every time, so a trigger that works in your normal browser can look broken there. To check that the pixel itself is installed, open Settings > Customer events in your Shopify admin.
The triggers
| Trigger | Starts when |
|---|---|
| Storefront Product Viewed | A shopper opens a product page |
| Storefront Collection Viewed | A shopper opens a collection page |
| Storefront Cart Viewed | A shopper opens the cart page |
| Storefront Product Added to Cart | An item is added to the cart |
| Storefront Product Removed from Cart | An item is removed from the cart |
| Storefront Checkout Started | A shopper begins checkout |
| Storefront Search | A search returns at least one result |
| Storefront Search Returned No Results | A search returns nothing |
| Out-of-Stock Variant Viewed | A shopper views a product page whose shown variant is sold out |
| Checkout Error Shown | Checkout displays an error to the shopper |
| Checkout Discount Code Rejected | A discount code is refused at checkout |
| B2B Buyer Visited | A signed-in B2B buyer visits the storefront |
| Signed-In Customer Visited | A signed-in customer visits the storefront |
| Custom Storefront Trigger | Your own event, published from your theme |
Out-of-Stock Variant Viewed
This one is worth reading closely, because it is the trigger most likely to behave differently from what the name suggests.
It is a restock demand signal: it tells you that a real shopper looked at something you cannot sell them. Paired with a Flow workflow it can tag the product, notify buying, or add the shopper to a waitlist.
It is derived, not reported. The shopper's browser has no idea what your inventory is, so the pixel sends a plain product view and the app decides against its own inventory records.
It checks a variant, not the whole product▾
The trigger fires on the variant the product page is showing, not on the product as a whole. A product with four in-stock variants and one sold-out variant fires only when the sold-out one is the one being shown.
That is why it is called Out-of-Stock Variant Viewed, and why the trigger gives your workflow both the variant and the product it belongs to.
Switching variant after the page loads is not detected▾
Shopify reports a product view when the shopper lands on the page. Clicking through the variant picker afterwards is a change of state inside the page, not a new page view, so Shopify does not report it and the app never learns about it.
In practice: a link straight to the sold-out variant (a ?variant= URL, or arriving from a collection where it is the shown option) fires. Landing on an in-stock default and then selecting the sold-out one does not.
If you need that, publish your own event on variant change from your theme with Custom Storefront Triggers.
Out of stock means zero or less across all locations▾
The app adds up the available quantity at every location that stocks the variant. The trigger fires when that total is zero or below.
Two consequences worth planning for:
- Locations that do not serve your online store still count. Stock sitting in a warehouse or a retail location that is not a sales channel for this product makes the total look healthy, so the trigger stays quiet even though the shopper cannot buy it.
- Overselling is not considered. A variant set to continue selling when out of stock is still purchasable at zero, so the trigger fires while the shopper can in fact complete the order.
Enabling it also enables Storefront Product Viewed▾
It has to. The out-of-stock decision is made from a product view, so the app must receive every product view to find the few that matter.
That means every product view counts towards your allowance, not only the out-of-stock ones. On a high-traffic store this is the single most expensive trigger in the app, and the cost is driven by your traffic, not by how often you sell out.
We force the dependency on rather than hiding it, so that the number on your usage page is never a surprise.
It needs inventory to have been synced▾
The app compares against its own inventory records. If a variant has never been synced, the app does not know its stock level and stays quiet rather than guessing - reporting an unsynced variant as sold out would be worse than reporting nothing.
Inventory syncs automatically when you enable the trigger. You can re-run it any time from the Triggers page.
Searches
Search gives you two triggers, and a single search fires exactly one of them:
- Storefront Search Returned No Results when the search found nothing. This is the one most stores want: it is a list of things shoppers expected you to sell.
- Storefront Search when the search found something.
Because they are mutually exclusive you can safely enable both without double counting. Storefront Search also carries the first result as a product reference, so a workflow can act on what the shopper most likely saw.
Visit triggers
B2B Buyer Visited and Signed-In Customer Visited fire when a signed-in shopper is on your storefront. They are the way to react to a customer coming back - re-engagement, account-manager alerts, a note on the record.
A shopper browsing ten pages is one visit, not ten events. The app collapses repeats into a visit window you choose per trigger with the settings icon next to its switch. Inside that window a shopper counts once.
- B2B Buyer Visited collapses per company, so two buyers from the same company in one window are one visit.
- Signed-In Customer Visited collapses per customer.
Set the window to zero to fire on every page view. On a store with signed-in traffic that is a lot of events, so start high and lower it if you need finer granularity.
Checkout triggers
Checkout Error Shown fires whenever checkout displays an error to a shopper: an address that will not validate, a payment that was declined, a field that will not accept what was typed. It is a way to find out that checkout is failing without waiting for a support ticket.
Checkout Discount Code Rejected narrows that to one case: checkout refused a discount code. That is usually an expired campaign, a code shared beyond its limits, or a code from an email that was never activated - all things worth knowing quickly.
Shopify does not tell apps which code was typed, so the trigger carries Shopify's rejection message (in the shopper's language) but not the code itself. Clicking apply with an empty field shows the same message, so the two cannot be told apart. Use it to spot a rise in rejected codes, not to identify a specific campaign.
Next steps
- Custom Storefront Triggers - publish your own events from your theme, for cart drawers and anything else Shopify does not report.
- Plans and usage - what counts as an event, and how the allowance works.
- Permissions and data access - what each permission unlocks and what the app reads.
- Event history and troubleshooting - see what fired and what it carried.

