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.

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.

Pass consent from your own banner to Shopifyjavascript
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