For the complete documentation index, see llms.txt. This page is also available as Markdown.

Shopify

The Omnata Shopify plugin is able to sync data inbound and outbound.

The Omnata plugin uses the Shopify GraphQL Admin API, currently pinned to version 2026-04.

On this page, you'll find:

Authentication methods

Field
Required
Description

Your Shopify Store URL

Yes

Your shop's *.myshopify.com URL. See Obtain your shop name.

Admin API access token

Yes

The Admin API access token of the custom app you created in Shopify. Stored as a Snowflake secret. See Generate your API Access Token.

User Tier

Yes

Your Shopify plan tier (Standard, Advanced, Shopify Plus, Enterprise). Determines the API rate limits Omnata applies. See Obtain your User Tier.

The plugin supports two ways to authenticate to your Shopify store. New connections should use Client Credentials — it's the path Shopify supports for new apps created in 2026 and beyond. The legacy Admin API access token method is retained for stores that already have an access token issued from a custom app created before 1 January 2026.

Both methods share the same supporting fields: your shop URL and your User Tier. The next section explains those.

Common connection fields

Regardless of which authentication method you choose, every connection requires these:

Field
Required
Description

Your Shopify Store URL

Yes

Your shop's *.myshopify.com URL. See Obtain your shop name.

User Tier

Yes

Your Shopify plan tier. Determines the API rate limits Omnata applies. See Obtain your User Tier.

Obtain your shop name

  1. Visit your store page.

  2. Click on Settings on the bottom left of your main store page.

  3. Copy down your shop name from the URL of the Settings page (the part before .myshopify.com).

Every Shopify store has a *.myshopify.com URL, even if you've configured a custom domain. Always use the myshopify.com form in the connection field.

Obtain your User Tier

  1. In your Shopify admin, go to Settings → Plan.

  2. Identify your current Shopify plan and choose the matching User Tier in the Omnata connection form:

Shopify plan
User Tier to select

Basic Shopify

Basic

Shopify

Shopify

Advanced Shopify

Advanced

Shopify Plus

Shopify Plus

Enterprise

Enterprise

The User Tier you choose drives the per-second and per-minute API rate limits Omnata applies — see Managing performance for the values.

Client Credentials (Client ID / Client Secret)

Recommended for all new connections. This method follows Shopify's OAuth 2.0 client-credentials grant — Omnata exchanges your app's Client ID and Client Secret for a short-lived Admin API access token (24-hour lifetime) and automatically refreshes it.

Connection fields

In addition to the Common connection fields above, this method requires:

Field
Required
Description

Client ID

Yes

The app's Client ID, copied from the Shopify Developer Dashboard.

Client Secret

Yes

The app's Client Secret. Stored as a Snowflake secret.

Steps to obtain a Client ID and Client Secret

These steps describe the high-level flow. Shopify updates the Developer Dashboard UI from time to time — refer to Shopify's client credentials grant guide.

  1. Create a new app. Give it a descriptive name (e.g. Omnata Sync).

  2. Configure the app's API access scopes. We recommend granting read (and write, for outbound) access to every Shopify object you intend to sync — the scopes you'll need per stream are listed under Generate your API Access Token and apply identically here.

  3. Install the app on the store you want to sync from. (Generate an installation URL from the dashboard and open it in a browser session for the store owner / admin.)

  4. After installation, the app's overview page shows the Client ID and Client Secret. Copy both immediately and store the Client Secret somewhere safe — once revealed, it should be treated like a password.

  5. Paste both values into the Omnata connection form, along with your shop URL and User Tier.

API Access Token

Legacy method. Use this only if you already have an Admin API access token from a custom app created in the Shopify admin before 1 January 2026, or if you're connecting to a store where the Client Credentials grant is not viable.

Connection fields

In addition to the Common connection fields above, this method requires:

Field
Required
Default
Description

Admin API access token

Yes

The Admin API access token (prefixed shpat_) from your custom app. Stored as a Snowflake secret.

Generate your API Access Token

For stores that still have access to the legacy admin-side custom-app flow:

  1. In your Shopify admin, go to Settings → Apps and sales channels → Develop apps.

  2. Click Allow custom app development if prompted (on both screens).

  3. Click Create an app, give it a name, then click Create App.

  4. Open the Configuration tab, and under Admin API Integration click Configure.

  5. Choose the access scopes you need. We recommend enabling read (and write, if you're using outbound) access for all the Shopify objects you intend to sync. The next section breaks down the minimum scopes per stream if you'd prefer to grant least-privilege access.

    A missing scope for a single field will cause the whole stream to fail mid-sync, so err on the side of including a scope rather than excluding it.

Scopes for inbound syncs

customers\

  • read_customers (mandatory)

products\

  • read_products (mandatory)

  • read_publications (for availablePublicationsCount field)

orders\

  • read_orders (mandatory)

  • read_customer (for customer field)

  • read_products (for line_items -> variant field)

  • read_payment_terms (for paymentTerms field)

returns (dep. orders)\

  • all scopes from orders

  • read_returns (mandatory)

fulfillments (dep. orders)\

  • all scopes from orders

  • read_fulfillments (mandatory)

  • read_locations (for location field)

shippingLine (dep. orders)\

  • all scopes from orders

product_variants\

  • read_products (mandatory)

  • read_inventory (for duplicateSkuCount field)

  • read_shipping (for duplicateSkuCount field)

locations\

  • read_locations (mandatory)

shopifyPaymentsAccount\

  • read_shopify_payments_accounts (mandatory)

balanceTransactions\

  • read_shopify_payments_accounts (mandatory)

payouts\

  • read_shopify_payments_accounts (mandatory)

shop\

  • read_products (for allProductCategoriesList field)

  • read_locations (for location field)

  • read_markets (for marketWebPresence field)

  • read_legal_policies (for shopPolicies field)

  • read_locales (for alternateLocales field)

inventory_items\

  • read_inventory (mandatory)

inventory_levels (dep. inventory_items)\

  • read_inventory (mandatory)

  • read_locations (for locations field)

Scopes for outbound syncs
  • Customers

    • write_customers

  • Products

    • write_products

  • Orders

    • write_orders

  • Fulfillment

    • write_fulfilments

  1. Click Save.

  2. At the top right of the page click Install app and complete the installation.

  3. After installation, an Admin API access token (prefixed shpat_) is generated. Copy it immediately — Shopify only shows it once.

API key vs Admin API access token. Under API Credentials you'll see an API key and an API secret key. These are not the value you paste into Omnata's "Admin API access token" field — that's the shpat_* token shown on installation. The Admin API access token is not viewable again after the first reveal; store it somewhere safe (e.g. a password manager) in case you need to reconfigure the connection later.


Inbound Syncs

All inbound syncs use Shopify's GraphQL Admin API. Each stream's primary key is id and uses a source-defined cursor.

Stream
Sync strategies
Depends on
Notes

Full Refresh, Incremental

Full Refresh, Incremental

Full Refresh, Incremental

Synced via the GraphQL bulk operations API.

Full Refresh

orders

Returns attached to orders pulled in the current sync window.

Full Refresh

orders

Shipping line items attached to orders pulled in the current sync window.

Full Refresh

orders

Refund adjustment records attached to orders pulled in the current sync window.

Full Refresh

orders

Fulfillment records attached to orders pulled in the current sync window.

Full Refresh

order_fulfillments

Line items inside the fulfillments above.

Full Refresh, Incremental

Full Refresh

Synced via the GraphQL bulk operations API.

Full Refresh, Incremental

inventory_items

Full Refresh, Incremental

Full Refresh

Full Refresh

Shopify Payments account details. (Note: the stream is currently named paymens_account — a typo in the source plugin. This is expected to be renamed in a future release.)

Full Refresh

Full Refresh

analytics_hourly

Incremental

Hourly storefront analytics via ShopifyQL. See ShopifyQL Analytics.

analytics_daily

Incremental

Daily storefront analytics via ShopifyQL. See ShopifyQL Analytics.

analytics_weekly

Incremental

Weekly storefront analytics via ShopifyQL. See ShopifyQL Analytics.

analytics_monthly

Incremental

Monthly storefront analytics via ShopifyQL. See ShopifyQL Analytics.

ShopifyQL Analytics

The plugin exposes four inbound streams that surface storefront analytics from Shopify's ShopifyQL engine:

Stream
Granularity
Sync strategies

analytics_hourly

One row per hour

Incremental

analytics_daily

One row per day

Incremental

analytics_weekly

One row per week

Incremental

analytics_monthly

One row per month

Incremental

These streams use ShopifyQL rather than the Admin GraphQL API. The numbers come directly from Shopify's own storefront analytics engine, so they match what you see in the Shopify Analytics dashboard.

Each granularity is a separate stream (and therefore a separate Snowflake table). Sync just one (e.g. analytics_daily for BI dashboards) or all four for finer-grained drill-downs.

On the first sync the plugin walks back 365 days of history. Subsequent runs resume from the stored cursor (latest_period_end).

Columns

All four streams share the same schema. Each row represents one time bucket at the chosen granularity.

Identifiers

Column
Type
Nullable
Description

id

string

No

Synthetic primary key: {granularity}_{period_start}

period_start

string

No

Start of the time bucket

Session metrics

Column
Type
Nullable
Description

sessions

integer

Yes

Number of online store visits

online_store_visitors

integer

Yes

Unique visitors

conversion_rate

number

Yes

Visits that resulted in a sale (decimal ratio)

bounce_rate

number

Yes

Visits that ended after a single pageview (decimal ratio)

average_session_duration

number

Yes

Average visit duration in seconds

pageviews

integer

Yes

Total pageviews across all visits

added_to_cart_rate

number

Yes

Visits with items added to cart (decimal ratio)

reached_checkout_rate

number

Yes

Visits that reached checkout (decimal ratio)

sessions_with_cart_additions

integer

Yes

Visits in which a visitor added an item to cart

sessions_that_completed_checkout

integer

Yes

Visits in which a purchase was completed

Sales metrics

Column
Type
Nullable
Description

total_sales_from_new_customers

number

Yes

Total sales amount from new customers

total_sales_from_returning_customers

number

Yes

Total sales amount from returning customers

Rate columns land as decimal ratios (0.0 - 1.0), not percentages (0 - 100). All metric columns are nullable -- ShopifyQL returns null for periods with no traffic.

How dependent streams work

Streams marked as depending on another (e.g. order_returns depends on orders) are only populated for parent records that appear in the same sync. This means a Full Refresh of order_returns returns only the returns for orders fetched in that sync — pair it with a Full Refresh of orders if you need complete coverage.

Bulk vs basic GraphQL operations

The plugin uses Shopify's GraphQL bulk operations for large streams and falls back to standard paginated GraphQL when the volume is below a threshold (currently 500 records). The behaviour per stream is:

Mode
Streams
Behaviour

Basic only

locations, shop, payments_account, balance_transactions, payouts

Always uses the standard paginated GraphQL API.

Bulk only

orders, inventory_items

Always uses the bulk operations API. If a tenant-wide bulk operation is already in progress, the plugin waits for it to finish before submitting its own.

Basic + bulk

customers, products

Uses bulk when the result set is above the threshold; falls back to basic GraphQL otherwise.

Dependent

order_returns, order_shipping_lines, order_refund_adjustments, order_fulfillments, order_fulfillment_line_items, inventory_levels

Populated as a by-product of the parent stream's bulk operation — no independent API calls.

Handling Deletes

Shopify doesn't expose a general change-feed for hard-deleted records on most resources — once an object is deleted, it simply stops appearing in subsequent API responses. The Omnata Shopify plugin does not actively reconcile deletes during incremental syncs.


Outbound Syncs

Supported Outbound sync strategies: Create, Update, Upsert, Delete.

You should structure your source data as described in Outbound sync data structures.

The following streams for these objects are supported:

  • customer

    • Create - Creates a new customer.

    • Update - Updates an existing customer's information.

    • Upsert - Creates a new customer or updates an existing customer's information.

    • Delete - Deletes an existing customer.

Existing customers cannot be deleted if they have a pending order.

  • products

    • Create - Creates a new product.

    • Update - Updates an existing product's information.

    • Upsert - Creates a new product or updates an existing product's information.

    • Delete - Deletes an existing product.

  • orders

    • Create - Creates an order.

    • Update - Updates an existing order's information.

    • Upsert - Creates an order or updates an existing order's information.

    • Delete - Deletes an existing order.

  • fulfillments

    • Create - Fulfills an existing unfulfilled order.

    • Update - Updates an existing fulfillment's information.

    • Upsert - Fulfills an existing unfulfilled order or updates an existing fulfillment's information.

    • Delete - Cancels an already fulfilled order.

  • product variants

    • Create - Creates a product variant from on a product.

    • Update - Updates the product variant information.

    • Upsert - Creates a product variant if it does not exist or updates an existing's product variant's information.

    • Delete - Deletes a product variant from a product.

  • inventory item levels

    • Create - Creates an inventory level at a specified location with the location id.

    • Update - Updates the inventory level stock amount.

    • Upsert - Creates an inventory level at a specified location with the location id or update the inventory level stock amount if the inventory level does not exist.

    • Delete - Deletes the entire inventory level.

Inventory levels cannot be deleted if this is the last remaining inventory level of the product variant.


Managing performance

API rate limits per plan

The User Tier you select on the connection determines the per-second and per-minute REST request rate limits Omnata applies for the plugin. These values are aligned to Shopify's published API rate limits:

User Tier
Requests / second
Requests / minute

Basic

2

40

Shopify

2

40

Advanced

4

40

Shopify Plus

20

400

Enterprise

40

400

If you upgrade or downgrade your Shopify plan, update the User Tier on the connection accordingly so Omnata throttles correctly.

Bulk operations

Shopify has an API feature called bulk operations that offer much higher throughput than standard GraphQL queries. The Omnata plugin attempts to use these where possible to speed up sync times, falling back to regular queries where they cannot be executed.

For streams and target objects that support both modes, the plugin attempts bulk operations:

  • For inbound syncs, for each stream, if the expected record count for this sync is at or above inbound_bulk_threshold (default 500).

  • For outbound syncs, for each target objects, when the number of records in the sync run is at or above outbound_bulk_threshold (default 50).

  • If below, it fall back to paginated GraphQL queries

Concurrency

Shopify allows a limited number of bulk operations per shop at a time.

If bulk operations are already in flight (started either by Omnata or by another integration), the plugin will wait for it to finish before submitting another. The maximum wait is 1 hour, after which the plugin falls back to the basic paginated API for streams that support both modes.

Contention with other integrations - If another app on the same Shopify store is also running bulk operations, Omnata will see the same "already in progress" responses and follow the same wait-then-fallback behaviour. On busy shops you may see basic + bulk streams fall back to paginated GraphQL more often during peak periods.

Disable bulk operations

You can force paginated GraphQL on a basic + bulk stream by setting the non_bulk_override sync parameter to true. This applies regardless of record count. Bulk-only streams (orders, inventory_items) ignore it.

Last updated