A regular (non-sales-channel) app can subscribe to COLLECTION_PUBLICATIONS_* and PRODUCT_PUBLICATIONS_* with zero errors, and then never receive a delivery for anything published or unpublished to the Online Store. The subscription looks healthy in every API response, so nothing tells you your coverage is imaginary.
I ran a positive control so this isn’t a “your endpoint is broken” or “delivery was slow” report.
Setup (dev store, 2026-07): an app holding read_publications + read_product_listings (no write_publications, not a sales channel). Five subscriptions created via webhookSubscriptionCreate, every one returning userErrors: []:
COLLECTION_PUBLICATIONS_CREATE/UPDATE/DELETEPRODUCT_PUBLICATIONS_CREATE/DELETE
Eight real publication transitions, one delivery:
| # | Action | Object | Publication | Delivery |
|---|---|---|---|---|
| 1 | publish | collection | Online Store | — none |
| 2 | unpublish | collection | Online Store | — none |
| 3 | re-publish | collection | Online Store | — none |
| 4 | publish | collection | the subscribing app’s own publication | collection_publications/create |
| 5 | auto-publish on create | product | Microsoft Copilot (a different app’s publication) | — none |
| 6 | publish | product | Online Store | — none |
| 7 | unpublish | product | Online Store | — none |
| 8 | re-publish | product | Online Store | — none |
The one delivery arrived 1.4 seconds after the change (x-shopify-triggered-at: 2026-07-29T16:06:15.845Z, received 16:06:17), carrying publication_id = the app’s own publication. So the topic, the subscription and the delivery path all work — they are simply scoped to the subscribing app’s own publication.
Confounds ruled out:
- Not latency: the successful delivery took 1.4s; the Online Store transitions were given 20+ minutes.
- Not a missing topic in the pinned version: these topics exist in both 2025-10 (what
webhookSubscriptionCreatepins subscriptions to) and 2026-07. - Not a dead subscription: all five verified still present, with the correct callback URL, after the test.
- Not scope-related: the app holds
read_publications, and no scope change was made during the experiment. - All transitions were made through the Admin UI and confirmed server-side via
resourcePublications(isPublished+publishDate).
What I’d like to ask:
- If own-publication scoping is intentional, please reject the subscription for apps that don’t own a publication — or document it prominently on the topic reference. Silently accepting a subscription that can never fire is the worst of both worlds: an app ships believing it has coverage, and only discovers otherwise when merchant data quietly goes stale.
- If it is not intentional, then Online Store publication changes are missing deliveries.
- Either way: is there any supported way for a non-sales-channel app to learn that a product or collection was published to / unpublished from the Online Store, without polling? For a merchandising app such as Depict this is a real gap — an unpublished collection has to disappear from our UI and a re-published one has to come back, and today the only mechanism we have is periodic reconciliation plus inferring publish state from
products/updatepayloads. I’d be glad to be told I’ve missed the obvious topic.
Happy to share the store, the subscription ids and the raw capture with staff.