Currently Shopify sends identifying information about the shopify store that a webhook payload is for, but it doesn’t send which Shopify Client ID or which webhook subscription caused the webhook to be delivered. This information is captured and displayed in the Delivery Logs in the partners dashboard, but it’s not sent in any headers.
If you have more than one Shopify application running on the same set of servers, this makes identifying which application an incoming payload is for harder! If you have an exact 1-1 mapping between infrastructure and client IDs, then you implicitly know which client ID you are, but if you have multiple, there’s no clear indicator in the payload. The reasons for having multiple client IDs around might be:
- cost optimization, where you run multiple apps in the same process or against the same database just to save on costs for deploying more than one app
- temporary migrations from one client ID to another
- multitenant platforms like integrations providers or Gadget that host many Shopify apps
If you do have multiple client IDs, one way to identify which client ID caused a webhook to be sent is to check the HMAC of the payload against all the client secrets that could have possibly caused the webhook to be sent. Whichever client secret validates the HMAC is the one that sent it. This strategy is prohibitively expensive if you have many client IDs thought.
Another strategy for identifying which client sent a payload is to put the client ID in an HTTPS webhook subscription URL. This allows you to know which client sent a payload because you can create dynamic URL patterns in your application, and pass information back to yourself within that URL. I currently do this to work around this problem, with URLS like:
// for client id 1
"https://myapp.gadget.com/api/shopify/webhooks/1"
// for client id 2
"https://myapp.gadget.com/api/shopify/webhooks/2"
But, this strategy doesn’t work for the EventBridge / GCP PubSub subscriptions that Shopify recommends, because you can’t do dynamic topic patterns in these systems, just static topic names. GCP also has hard limits on the number of topics you can create total, and its expensive infrastructure-wise to subscribe to a lot of topics at the same time, so ideally we could put all our webhooks on the same topic, like:
all-webhook-payloads
and then inspect the individual payloads for which client id they are for.
Any chance we could get the client id added as a webhook header and pubsub metadata item?