Stop webhooks call for product updates originating from shopify API

IAmADev
Shopify Partner
19 0 8

Hi there!

I have set up a webhook that will call my server anytime there is an update on a shop's product. 

It's working nicely but I would like to know if it's possible to make this webhook not call my server when the updates was not made by the shop's owner directly but through shopify's API.

The problem currently is that when I use shopify API to make an update to a product this triggers the product/update webhook which in turns call my server and duplicates the effect of such product update on my side. 

 

Thanks for your help!

Replies 21 (21)

vixnguyen
Shopify Partner
45 4 4

Hi,

Unfortunately, There is no way to do so. Please refer to this comment for further info.

IAmADev
Shopify Partner
19 0 8

Hi, 

Ok, that is quite problematic. Is there any plan to allow for this ?

vixnguyen
Shopify Partner
45 4 4

Hi,

I'm not sure. But please explain your use case of using Webhook, so that I can advise another approach.

IAmADev
Shopify Partner
19 0 8
Hi,

Basically I've setup webhooks for when a user creates or updates a product.
This webhook calls my server and updates the state of my app which is
tracking those changes.
But sometimes my app is the one initiating those product creates & updates
through a call to the Shopify api. In these situations I don't want the
shopify webhook to tell me again about those changes, because I've already
updated the state of my app accordingly. These webhook calls are
duplicating those changes.
My solution right now is to keep deleting & re-creating these shopify
webhooks when the product create & update are not done by a user.
But this is cumbersome, it generates traffic to your api for nothing and
it's error prone..
vixnguyen
Shopify Partner
45 4 4

Hi,

I don't think deleting & re-creating webhook is a good solution.

 

But sometimes my app is the one initiating those product creates & updates
through a call to the Shopify api

In this case, you can add a custom field named "actor" with value "API", so that it's easy for you to filter if the product create/update events caused by yourself or by users from webhooks payload. Do nothing and response with status 200 when receiving an event from "actor": "API"  . How do you think?

IAmADev
Shopify Partner
19 0 8

Sounds like an interesting solution yes, I didn't know you could arbitrarily create product fields like that, aren't you supposed to respect the fields listed in the Product API payload when you create/update a product via the API ?

IAmADev
Shopify Partner
19 0 8

I've tried but yeah it seems Shopify doesn't include this custom field inside the webhook call.. 
Here is the webhook call payload from the doc: https://shopify.dev/docs/api/admin-rest/2022-10/resources/webhook#event-topics
If you check the products/create topic there seems to be a restricted list of fields that can be attached to a product..

vixnguyen
Shopify Partner
45 4 4

Hi,

- Create a custom field as a Shopify Metafields

- You can subscribe to get the Metafields inside webhook, please refer to this link.

Please try again.

IAmADev
Shopify Partner
19 0 8

Ah yes so you need to register metafields etc, it's quite a process !
This can do the trick for Creates, but this is not suitable for Updates because once I set "actor": "API"  for a product update made through the API, it will stay with this value forever even when more recent updates were made by the user through the UI..

IAmADev
Shopify Partner
19 0 8

Or that would mean any time the user makes an update to a Product he should also update the Actor metafield value from "API" to "UI" which is definitely a terrible UX.

vixnguyen
Shopify Partner
45 4 4

Hi,


update the Actor metafield value from "API" to "UI"

It would be updated by webhooks handler instead of end-user. It means, after you receive an event from webhooks with Actor: API, you have to do 2 things:

- 1st, do your business work

- 2nd, revert Actor empty or UI or whatever you want.

IAmADev
Shopify Partner
19 0 8

But the webhook can be triggered by both UI & API ! I need to know who has triggered that webhook in order to set in the metafields who has triggered that webhook in order to know who has triggered that webhook. It's an infinite loop ://

IAmADev
Shopify Partner
19 0 8

I appreciate the time you take to look for a solution here though ! Thanks for this man ! I'm just frustrated by this missing feature in the Webhook api :))

vixnguyen
Shopify Partner
45 4 4

Hi,

I think you did not really want to try to solve your issue, you're finding an easy way to do it. There is no infinite loop, let's have a look as the sample code below:

if (actor === 'API') {
  // handle business logic here
  // update product actor = 'UI' -> it would call the webhook one more time and return -> there is no thing happens after that -> no infinity loop
} else {
  return; // do nothing
}

 

IAmADev
Shopify Partner
19 0 8

Hey !
Let me recap this so you can see why this is not solving the isssue:

if (actor == 'API') {
  // No business logic here, I just want to discard the call because the update came from my service through the API
  // update product actor = 'UI' -> This will trigger the Shopify webhook again which will call this same handler and go to the "else" part now that actor != 'API'.
} else {
  // If I reach this code that means the shopify webhook has been triggered by the user through the UI (because actor != 'API')
  // In that case I need to process this update and send the data to my other service. But I really only want to do this if the user has done the update. If it's not the user that means my service was the originator of the update and has already processed it on its end. We don't to do this process twice.
  // But because just above we update the metafields to actor == 'UI', we trigger again the update webhook which will call again this handler and this time will actually reach that code here even if it's not the result of a UI update.. So my service will get called here for an update it doesn't want to process.
}
vixnguyen
Shopify Partner
45 4 4

Hi,

I see, so in this case we should do the reverse:

if (actor == 'API') {
  // No business logic here, I just want to discard the call because the update came from my service through the API
} else {
  // do business logic here
  // update product actor = 'API' -> This will trigger the Shopify webhook again which will call this same handler and go to the "if" part then do nothing.
IAmADev
Shopify Partner
19 0 8

I thought about this but this doesn't work because actor never gets set to 'UI' anymore with this logic. So updates triggered by UI will never reach the "else" part. 

IAmADev
Shopify Partner
19 0 8

Hence the infinite loop I was talking about.
And all this just because there is no way to differentiate the origin of a webhook trigger, it's really frustrating..

IAmADev
Shopify Partner
19 0 8

I guess you agree now that it's a bit of a deadlock :))

dbolesta
Visitor
1 0 0

Hey @IAmADev, we are experiencing a similar issue. We have a Lambda function that can update our Shopify products via the API, and we would really like the Product Updates Webhook to not fire if the product is updated this way. 
I can see you have outlined the problem thoroughly, and its only been a couple of weeks, but wondering if you've found any solutions for this problem.

We are trying to solve this too, and will happily share any progress if we are able to make any.

IAmADev
Shopify Partner
19 0 8

Hey @dbolesta !
Well not with the help of Shopify unfortunately..
What you can try is, inside your lambda, insert in some redis cache the product id you're about to update. Then let the Shopify api trigger that webhook anyway but inside that webhook handler read the cache to see if the related product id is the same as the one your lambda inserted earlier. If yes return early and if not process the update.
You can determine some time to live to that cache entry to more or less prevent legit product update made by a user soon after the api made ones. Few seconds should do the trick :))