Skip to content

Latest commit

 

History

History
162 lines (121 loc) · 7.27 KB

webhooks.md

File metadata and controls

162 lines (121 loc) · 7.27 KB

Webhooks

Table of contents

App-specific webhooks in shopify.app.toml (recommended) Manage shop-specific webhooks using ShopifyApp::WebhooksManager Mandatory Privacy Webhooks

App-specific webhooks in shopify.app.toml (recommended)

You can specify app-specific webhooks to subscribe to in the shopify.app.toml file. These subscriptions are easier to manage because they are kept up to date by Shopify. In many cases they will be sufficient. Please read app-specific vs shop-specific subscriptions to understand when you might need shop-specific webhooks.

Consuming app-specific webhooks events

To consume app-specific webhooks events from the shopify.app.toml file, you can scaffold the necessary files by running the following generator.

rails g shopify_app:add_declarative_webhook --topic carts/update --path webhooks/carts_update

This will add a new controller, job, and route to your application. The controller will verify the webhook and queue the job to process the webhook. The job will be responsible for processing the webhook data.

Manage shop-specific webhooks using ShopifyApp::WebhooksManager

See ShopifyApp::WebhooksManager. ShopifyApp can manage your app's shop-specific webhooks for you if you set which webhooks you require in the initializer:

ShopifyApp.configure do |config|
  config.webhooks = [
    {topic: 'carts/update', path: 'api/webhooks/carts_update'}
  ]
end

This method should only be used if you have a good reason not to use app-specific webhooks (such as requiring different topics for different shops).

When the OAuth callback or token exchange is completed successfully, ShopifyApp will queue a background job which will ensure all the specified webhooks exist for that shop. Because this runs on every OAuth callback, it means your app will always have the webhooks it needs even if the user uninstalls and re-installs the app.

ShopifyApp also provides a WebhooksController that receives webhooks and queues a job based on the received topic. For example, if you register the webhook from above, then all you need to do is create a job called CartsUpdateJob. The job will be queued with 2 params: shop_domain and webhook (which is the webhook body).

If you would like to namespace your jobs, you may set webhook_jobs_namespace in the config. For example, if your app handles webhooks from other ecommerce applications as well, and you want Shopify cart update webhooks to be processed by a job living in jobs/shopify/webhooks/carts_update_job.rb rather than jobs/carts_update_job.rb):

ShopifyApp.configure do |config|
  config.webhook_jobs_namespace = 'shopify/webhooks'
end

If you are only interested in particular fields, you can optionally filter the data sent by Shopify by specifying the fields parameter in config/webhooks. Note that you will still receive a webhook request from Shopify every time the resource is updated, but only the specified fields will be sent.

ShopifyApp.configure do |config|
  config.webhooks = [
    {topic: 'products/update', path: 'api/webhooks/products_update', fields: ['title', 'vendor']}
  ]
end

If you need to read metafields, you can pass in the metafield_namespaces parameter in config/webhooks. Note if you are also using the fields parameter you will need to add metafields into that as well. Shopify documentation on metafields in webhooks can be found here.

ShopifyApp.configure do |config|
  config.webhooks = [
    {
      topic: 'orders/create',
      path: 'api/webhooks/orders_create',
      metafield_namespaces: ['app-namespace'],
    },
  ]
end

If you need to filter by webhook fields, you can register a webhook with a filter parameter. The documentation for Webhook filters can be found here.

ShopifyApp.configure do |config|
  config.webhooks = [
    {
      topic: 'products/update',
      path: 'api/webhooks/products_update',
      filter: "variants.price:>=10.00",
    },
  ]
end

If you'd rather implement your own controller then you'll want to use the ShopifyApp::WebhookVerification module to verify your webhooks, example:

class CustomWebhooksController < ApplicationController
  include ShopifyApp::WebhookVerification

  def carts_update
    params.permit!
    SomeJob.perform_later(shop_domain: shop_domain, webhook: webhook_params.to_h)
    head :no_content
  end

  private

  def webhook_params
    params.except(:controller, :action, :type)
  end
end

The module skips the verify_authenticity_token before_action and adds an action to verify that the webhook came from Shopify. You can now add a post route to your application, pointing to the controller and action to accept the webhook data from Shopify.

The WebhooksManager uses ActiveJob. If ActiveJob is not configured then by default Rails will run the jobs inline. However, it is highly recommended to configure a proper background processing queue like Sidekiq or Resque in production.

ShopifyApp can create webhooks for you using the add_webhook generator. This will add the new webhook to your config and create the required job class for you.

rails g shopify_app:add_webhook --topic carts/update --path webhooks/carts_update

Where --topic is the topic and --path is the path the webhook should be sent to.

Mandatory Privacy Webhooks

We have three mandatory privacy webhooks

  1. customers/data_request
  2. customer/redact
  3. shop/redact

The generate shopify_app command generated three job templates corresponding to all three of these webhooks. To pass our approval process you will need to set these webhooks in your partner dashboard. You can read more about that here.

EventBridge and PubSub Webhooks

You can also register webhooks for delivery to Amazon EventBridge or Google Cloud Pub/Sub. In this case the path argument to needs to be of a specific form.

For EventBridge, the path must be the ARN of the partner event source.

ShopifyApp.configure do |config|
  config.webhooks = [
    {
      delivery_method: :event_bridge,
      topic: 'carts/update',
      path: 'arn:aws:events....'
    }
  ]
end

For Pub/Sub, the path must be of the form pubsub://[PROJECT-ID]:[PUB-SUB-TOPIC-ID]. For example, if you created a topic with id red in the project blue, then the value of path would be pubsub://blue:red.

ShopifyApp.configure do |config|
  config.webhooks = [
    {
      delivery_method: :pub_sub,
      topic: 'carts/update',
      path: 'pubsub://project-id:pub-sub-topic-id'
    }
  ]
end

When registering for an EventBridge or PubSub Webhook you'll need to implement a handler that will fetch webhooks from the queue and process them yourself.