Skip to main content
Shopify is a leading e-commerce platform for creating and managing online stores. Connecting Shopify to Nekt lets you centralize core commerce data — orders, products, customers, inventory, collections, and locations — sourced from the Shopify Admin GraphQL API. With incremental syncs and consistent schemas, you can join Shopify with marketing, finance, and operations data to drive end-to-end analytics like revenue performance, cohort behavior, merchandising impact, inventory health, and fulfillment efficiency.

Configuring Shopify as a Source

In the Sources tab, click on the “Add source” button located on the top right of your screen. Then, select the Shopify option from the list of connectors. Click Next and you’ll be prompted to add your access.

1. Add account access

You’ll need a Shopify Admin API access token and your store identifier.
  • Access Token: The private app access token for authenticating API requests.
  • Store ID: The name of your Shopify store extracted from your store admin URL. Use only the store subdomain: https://[store].myshopify.com/adminStore ID = [store].
  • Start Date: The earliest record date to sync.
Important: As of January 1, 2026, you can no longer create new custom apps directly in the Shopify admin. You must use the Dev Dashboard to create new apps. Legacy custom apps created before this date can still be managed in the Shopify admin.
Follow these steps to create a custom app in Shopify and generate a long-lived (non-expiring) access token for Nekt:
1

Access the Dev Dashboard

  1. Log in to your Shopify store admin at https://[your-store].myshopify.com/admin
  2. Go to Settings > Apps
  3. Click Develop apps
  4. Click Build apps in Dev Dashboard to open the Dev Dashboard
2

Create a new Custom App

  1. In the Dev Dashboard, click Create app
  2. In the “Start from Dev Dashboard” section, enter a name for your app (e.g., “Nekt Data Integration”)
  3. Click Create
3

Configure your app version

  1. In the URLs section:
    • Set your App URL to https://shopify.dev/apps/default-app-home
    • Add https://developers.google.com/oauthplayground as an Allowed redirection URL
  2. Select a Webhooks API Version (use the latest stable version)
  3. In the Access section, enter the following scopes:
  4. Click Release
  5. Optionally enter a version name (e.g., “v1.0”) and message
  6. Click Release to confirm
4

Get your Client Credentials

  1. In the Dev Dashboard, go to your app’s Settings page
  2. Copy your Client ID and Client Secret
Important: The client secret is sensitive information. Store it securely and never expose it in frontend code or public repositories.
5

Open the Google OAuth Playground

Click the link below to open Google OAuth Playground pre-configured for Shopify:Open Shopify OAuth Playground →
6

Configure the OAuth Playground

In the OAuth Playground, click the gear icon (⚙️) on the right side to open “OAuth 2.0 configuration” and update these values:
  1. Replace SHOP_NAME with your store’s subdomain in both:
    • OAuth authorization endpoint: https://[your-store].myshopify.com/admin/oauth/authorize
    • OAuth token endpoint: https://[your-store].myshopify.com/admin/oauth/access_token
  2. Replace SHOPIFY_CLIENT_ID with your Client ID
  3. Replace SHOPIFY_CLIENT_SECRET with your Client Secret
  4. Click Close
7

Authorize and Get Your Access Token

  1. Click Authorize APIs (Step 1 in the playground)
  2. You’ll be redirected to Shopify - click Install app to grant permissions
  3. After returning to the playground, click Exchange authorization code for tokens (Step 2)
  4. Your access token will appear in the response on the right side
This token will remain valid indefinitely until you uninstall the app or rotate the client secret.
8

Copy your credentials for Nekt

You now have everything needed to configure Shopify in Nekt:
  • Access Token: The access_token from the response (starts with shpat_)
  • Store ID: Your store’s subdomain from https://[store-id].myshopify.com
If you created a custom app before January 1, 2026, you can still manage it directly from your Shopify admin. These legacy apps provide a simpler experience with non-expiring tokens:
1

Access Legacy Apps

  1. Go to Settings > Apps in your Shopify admin
  2. Find your app in the Legacy custom apps section
  3. Click on the app to manage its settings
2

View or Regenerate Access Token

  1. Go to the API credentials tab
  2. Click Reveal token once to view your access token
  3. Copy the token immediately - it’s only shown once
  4. If you need a new token, uninstall and reinstall the app
Legacy custom apps have non-expiring access tokens that are shown directly in the admin UI, making them simpler to use than new Dev Dashboard apps.
Once you’re done, click Next.

2. Select streams

Choose which data streams you want to sync — you can select all streams or pick specific ones that matter most to you. For faster extractions, select only the streams relevant to your analysis.
Tip: The stream can be found more easily by typing its name.
Select the streams and click Next.

3. Configure data streams

Customize how you want your data to appear in your catalog. Select the desired layer where the data will be placed, a folder to organize it inside the layer, a name for each table (which will effectively contain the fetched data) and the type of sync.
  • Layer: Choose between the existing layers on your catalog. This is where you will find your new extracted tables as the extraction runs successfully.
  • Folder: A folder can be created inside the selected layer to group all tables being created from this new data source.
  • Table name: We suggest a name, but feel free to customize it. You have the option to add a prefix to all tables at once and make this process faster!
  • Sync Type: You can choose between INCREMENTAL and FULL_TABLE.
    • Incremental: Every time the extraction happens, we’ll get only the new data — which is good if, for example, you want to keep every record ever fetched.
    • Full table: Every time the extraction happens, we’ll get the current state of the data — which is good if, for example, you don’t want to have deleted data in your catalog.
Once you are done configuring, click Next.

4. Configure data source

Describe your data source for easy identification within your organization, not exceeding 140 characters. To define your Trigger, consider how often you want data to be extracted from this source. This decision usually depends on how frequently you need the new table data updated (every day, once a week, or only at specific times). Optionally, you can determine when to execute a full sync. This will complement the incremental data extractions, ensuring that your data is completely synchronized with your source every once in a while. Once you are ready, click Next to finalize the setup.

5. Check your new source

You can view your new source on the Sources page. If needed, manually trigger the source extraction by clicking on the arrow button. Once executed, your data will appear in your Catalog.
For you to be able to see it on your Catalog, you need at least one successful source run.

Streams and Fields

Below you’ll find all available data streams from Shopify and their corresponding fields:
Important: The read_all_orders scope is required to access all historical orders. If not provided, only orders created in the last 60 days will be available.
Stream containing orders, transactions and line items. Supports incremental sync using updatedAt.Key Fields:
  • id - Unique identifier for the order
  • name - The order name (e.g., #1001)
  • legacyResourceId - Legacy numeric ID
  • email, phone - Contact information
  • processedAt, createdAt, updatedAt, cancelledAt, closedAt - Timestamps
  • confirmed - Whether the order is confirmed
  • currencyCode, presentmentCurrencyCode - Currency codes
Transactions:
  • transactions[].id, kind, status, gateway, authorizationCode, test, paymentId
  • transactions[].createdAt, processedAt
  • transactions[].amountSet.presentmentMoney.amount, currencyCode
  • transactions[].amountSet.shopMoney.amount, currencyCode
  • transactions[].parentTransaction.id
Totals:
  • totalPriceSet - Total price (shopMoney + presentmentMoney)
  • subtotalPriceSet - Subtotal price
  • totalShippingPriceSet - Total shipping
  • totalDiscountsSet - Total discounts
  • totalTaxSet - Total tax
  • totalWeight, taxesIncluded, taxExempt
Statuses and Flags:
  • displayFinancialStatus - Financial status (PAID, PENDING, REFUNDED, etc.)
  • displayFulfillmentStatus - Fulfillment status (FULFILLED, UNFULFILLED, PARTIAL, etc.)
  • fullyPaid, fulfillable, restockable, test, customerAcceptsMarketing
  • sourceName, sourceIdentifier, currentSubtotalLineItemsQuantity
  • tags, note, clientIp
Customer and Addresses:
  • customer.id, firstName, lastName, email
  • shippingAddress.* - Full shipping address
  • billingAddress.* - Full billing address
Discounts and Metafields:
  • discountCode, discountCodes[]
  • metafields[].id, namespace, key, value, type, description, createdAt, updatedAt
Sales Channel:
  • channelInformation.channelDefinition.handle
Line Items:
  • lineItems[].id, title, quantity, sku, vendor, variantTitle
  • lineItems[].customAttributes[].key, value
  • lineItems[].discountedTotalSet.*, originalTotalSet.*
  • lineItems[].discountAllocations[].allocatedAmount.amount, currencyCode
  • lineItems[].discountAllocations[].discountApplication.targetType, allocationMethod, targetSelection, title, description, code
  • lineItems[].variant.id, title, sku, product.id, product.title
Stream containing products, variants, images and metafields. Supports incremental sync using updatedAt.Key Fields:
  • id - Unique product identifier
  • title - Product title
  • descriptionHtml - HTML description
  • vendor - Vendor name
  • productType - Product type/category
  • handle - URL-friendly slug
  • createdAt, updatedAt, publishedAt - Timestamps
  • status - Product status (ACTIVE, ARCHIVED, DRAFT)
  • tags - Product tags
  • templateSuffix - Liquid template suffix
Options:
  • options[].id, name, position, values[]
Variants:
  • variants[].id, title, sku, price, position
  • variants[].inventoryPolicy - Inventory policy (DENY, CONTINUE)
  • variants[].compareAtPrice - Original price before discount
  • variants[].createdAt, updatedAt, taxable, barcode
  • variants[].inventoryItem.id - Link to inventory item
Images:
  • images[].id, altText, originalSrc
  • featuredImage.id, altText, originalSrc
Metafields:
  • metafields[].id, namespace, key, value, type, description
Stream containing inventory items, levels, and costing information. Supports incremental sync using updatedAt.Key Fields:
  • id - Unique inventory item ID
  • legacyResourceId - Legacy numeric ID
  • sku - Stock keeping unit
  • tracked - Whether inventory is tracked
  • trackedEditable.reason - Why tracked field is editable
  • requiresShipping - Whether item requires shipping
  • duplicateSkuCount - Count of duplicate SKUs
  • inventoryHistoryUrl - URL to inventory history
  • createdAt, updatedAt - Timestamps
Origin & Customs:
  • countryCodeOfOrigin, provinceCodeOfOrigin
  • harmonizedSystemCode
  • countryHarmonizedSystemCodes[].countryCode, harmonizedSystemCode
Inventory Levels (per location):
  • inventoryLevels[].id - Inventory level ID
  • inventoryLevels[].location.id, location.name - Location info
  • inventoryLevels[].item.id, item.sku - Item info
  • inventoryLevels[].quantities[].id, name, quantity, updatedAt - Quantity by type (available, committed, incoming, etc.)
Cost and Measurements:
  • unitCost.amount, unitCost.currencyCode
  • measurement.weight.unit, measurement.weight.value
  • locationsCount.count
Variant & Product:
  • variant.id, variant.title, variant.sku
  • variant.product.id, variant.product.title
Stream containing customer profiles. Supports incremental sync using updatedAt.Key Fields:
  • id - Unique customer ID
  • firstName, lastName
  • createdAt, updatedAt
  • verifiedEmail, taxExempt, tags, state
  • numberOfOrders - Total order count
Spend and Contacts:
  • amountSpent.amount, amountSpent.currencyCode
  • defaultEmailAddress.emailAddress, defaultEmailAddress.marketingState
  • defaultPhoneNumber.phoneNumber, defaultPhoneNumber.marketingState, defaultPhoneNumber.marketingCollectedFrom
Addresses:
  • addresses[].id, firstName, lastName, address1, city, province, country, zip, phone, name, provinceCode, countryCodeV2
  • defaultAddress.* - Same structure as addresses
Metafields:
  • metafields[].id, namespace, key, value, type, description
Stream containing product collections and included products. Supports incremental sync using updatedAt.Key Fields:
  • id, title, handle, description
  • publishedAt, updatedAt
Image:
  • image.altText, image.originalSrc
Products:
  • products[].id, title, handle, createdAt, updatedAt
  • products[].productType, vendor, tags, totalInventory, status, price, inventoryQuantity
  • products[].variants[].id, title, sku, price, inventoryQuantity
Sorting and Template:
  • sortOrder, sortType, sortValue, templateSuffix, url
Metafields:
  • metafields[].id, namespace, key, value, type, description
Stream containing store and warehouse locations. Uses full table sync.Key Fields:
  • id, name
  • active, activatable, deactivatable, deletable
  • createdAt, updatedAt, deactivatedAt
  • addressVerified, isFulfillmentService
Fulfillment Service:
  • fulfillmentService.id, fulfillmentService.serviceName
Address:
  • address.address1, address2, city, country, countryCode, province, provinceCode, zip
Metafields:
  • metafields[].id, namespace, key, value, type, description
Stream containing abandoned checkouts. Uses full table sync.Key Fields:
  • id - Unique identifier for the abandoned checkout
  • abandonedCheckoutUrl - URL for the abandoned checkout
  • createdAt, updatedAt, completedAt - Timestamps
  • taxesIncluded - Whether taxes are included
Price Sets:
  • subtotalPriceSet.presentmentMoney.amount, currencyCode
  • totalPriceSet.presentmentMoney.amount, currencyCode
  • totalTaxSet.presentmentMoney.amount, currencyCode
  • totalDiscountSet.presentmentMoney.amount, currencyCode
Customer:
  • customer.id, firstName, lastName, email, tags, state, note, createdAt, updatedAt
Addresses:
  • billingAddress.* - Address lines, city, province, country, zip, phone
  • shippingAddress.* - Address lines, city, province, country, zip, phone
Line Items:
  • lineItems[].id, title, sku, quantity
  • lineItems[].variant.id, variant.price
Taxes and Discounts:
  • discountCodes[]
  • taxLines[].rate, title, priceSet.presentmentMoney.amount, currencyCode

ShopifyQL Reports

In addition to the standard streams above, the Shopify connector supports ShopifyQL Reports — custom analytics queries written in ShopifyQL, Shopify’s analytics query language. This allows you to extract aggregated metrics directly from Shopify’s analytics engine, such as sales breakdowns, traffic data, and product performance reports. Each ShopifyQL report you configure becomes its own data stream with a dynamically discovered schema based on the query’s result columns.

How to configure ShopifyQL Reports

ShopifyQL Reports are configured as an advanced setting when setting up the Shopify source.
Your token needs to have the read_reports scope to be able to use ShopifyQL Reports.
1

Open Advanced Settings

When configuring your Shopify source access (step 1), look for the ShopifyQL Reports section under the advanced settings.
2

Add a report

Click Add to create a new report entry. Each report requires two fields:
  • Report name: A unique identifier for the report (letters, numbers, and underscores only). This becomes part of the stream name — for example, a report named daily_sales produces a stream called report_daily_sales.
  • ShopifyQL query: The full ShopifyQL query to execute. The query must be valid ShopifyQL syntax.
3

Add more reports (optional)

You can add as many ShopifyQL reports as needed. Each one becomes a separate stream that you can independently select and configure in the following steps.
ShopifyQL reports always run as full table syncs. Every execution re-runs the query and replaces the previous data. If your query includes a time range (e.g. SINCE -30d), the results will reflect the most recent window each time it runs.
The schema of each report is automatically discovered from the query results. If the query returns no data (e.g., the time range matches no records), schema discovery will fail. Make sure your query covers a time range that includes data.

ShopifyQL query examples

Below are ready-to-use ShopifyQL queries you can paste directly into the report configuration. Each example includes the recommended Report name and the Query to use.
Aggregated daily sales metrics including gross sales, discounts, returns, net sales, shipping, taxes, and total sales.Report name: daily_salesQuery:
Output columns:
Monthly aggregated sales for longer-term trend analysis.Report name: monthly_salesQuery:
Output columns:
Sales breakdown by product title, useful for identifying top-performing products.Report name: sales_by_productQuery:
Output columns:
Sales attributed to each traffic source, useful for marketing attribution.Report name: sales_by_referrerQuery:
Output columns:
Geographic breakdown of sales by customer billing country.Report name: sales_by_countryQuery:
Output columns:
Performance of each discount code, useful for evaluating promotion effectiveness.Report name: sales_by_discountQuery:
Output columns:
Daily order count with average order value for tracking purchasing patterns.Report name: daily_ordersQuery:
Output columns:

Working with ShopifyQL data

All ShopifyQL report columns are returned as String type, regardless of their original data type (money, number, percentage, etc.). Cast them to the appropriate types when querying in your Lakehouse:
ShopifyQL money values may include currency symbols or formatting depending on your store settings. If casting fails, you may need to strip non-numeric characters first.

Data Model

The following diagram illustrates the relationships between the core data streams in Shopify.

Use Cases for Data Analysis

This guide outlines valuable business intelligence use cases focused on inventory intelligence, helping you optimize stock levels, identify sales velocity, and prevent lost revenue from stockouts or overstocking. Run these queries on Explorer.

1. Inventory Health Dashboard

Get a comprehensive view of your inventory health by product, including stock levels, cost valuation, and risk classification across all locations. Business Value:
  • Identify products at risk of stockouts before they happen
  • Spot overstocked items tying up capital
  • Understand inventory distribution across locations
Inventory Status Distribution:

2. Sales Velocity & Days of Stock Remaining

Combine order data with inventory levels to understand how fast each product sells and estimate days of stock remaining — the core metric for preventing stockouts. Business Value:
  • Forecast when products will run out of stock
  • Prioritize reordering based on sales velocity
  • Identify fast-moving products that need safety stock buffers
Reorder Urgency Summary:
Products with STOCKOUT and CRITICAL urgency represent potential lost revenue. The “Revenue at Risk” column estimates how much revenue these products generated in the last 30 days — revenue you may lose if stock isn’t replenished.

3. Inventory Distribution by Location

Analyze how your inventory is distributed across fulfillment locations to optimize warehouse allocation and reduce shipping times. Business Value:
  • Balance inventory across warehouses to reduce shipping costs
  • Identify locations running low on key products
  • Optimize fulfillment routing
Location Inventory Share:
The West Coast Fulfillment location has the highest stockout rate at 6.2%. Consider redistributing stock from the Main Warehouse or increasing replenishment frequency for this location.

4. Inventory Turnover & Dead Stock Analysis

Identify products that aren’t selling (dead stock) versus those with healthy turnover, helping you make markdown, promotion, or discontinuation decisions. Business Value:
  • Free up capital tied in dead stock through markdowns
  • Identify candidates for clearance sales or bundles
  • Optimize purchasing decisions based on actual turnover rates
Stock Value by Turnover Category:
$24,750 in dead stock represents 30% of your total inventory value. Consider running clearance promotions, creating product bundles, or discontinuing these items to free up capital.

5. Abandoned Cart Recovery Intelligence

Analyze abandoned checkout data to understand lost revenue potential and identify high-value recovery opportunities. Business Value:
  • Quantify revenue lost from abandoned carts
  • Identify the most abandoned products to address pricing or UX issues
  • Prioritize recovery campaigns by cart value
5-Day Abandonment Summary:
At the current 18.6% recovery rate, improving recovery by just 5 percentage points (to ~24%) would capture an additional $2,800+ per week in revenue. Consider optimizing abandoned cart email timing, offering targeted discounts, or implementing SMS recovery flows.

Implementation Notes

GraphQL API

  • This connector uses the Shopify Admin GraphQL API for efficient data extraction
  • All monetary values are returned as strings (e.g., "29.99") — cast them to numeric types in your queries
  • The connector uses cursor-based pagination for optimal API performance

ShopifyQL Reports

  • ShopifyQL reports use a newer API version (2026-01) than the standard GraphQL streams (2025-07)
  • Reports always run as full table syncs (no incremental support)
  • The schema is automatically discovered at extraction time by executing the query and reading column metadata
  • If a query returns no data, schema discovery will fail — ensure your time range (SINCE / UNTIL) covers a period with data
  • ShopifyQL supports querying the sales, orders, products, and customers data models — refer to the ShopifyQL reference for the full syntax and available fields

Incremental Sync

  • Orders, Products, Inventory Items, Customers, and Collections support incremental sync using updatedAt
  • Locations, Abandoned Checkouts, and ShopifyQL Reports use full table sync
  • Use incremental sync for large stores to minimize API calls and extraction time

Nested Data Structures

  • Line items, transactions, variants, metafields, and inventory levels are stored as nested arrays
  • Use UNNEST (GCP) or CROSS JOIN UNNEST (AWS) to flatten these arrays in your queries
  • The connector automatically flattens GraphQL connection structures (edges/node) into clean arrays

Inventory Quantities

  • The inventoryLevels[].quantities[] array contains multiple quantity types per location:
    • available — Units available for sale
    • committed — Units reserved for unfulfilled orders
    • incoming — Units expected from incoming transfers
    • on_hand — Total physical units at the location
  • Filter by name to get the quantity type you need

Price Sets

  • Shopify provides monetary values in both shop currency (your store’s base currency) and presentment currency (the customer’s local currency)
  • Use shopMoney for internal reporting and presentmentMoney for customer-facing analysis

API Scopes Required

The Shopify connector requires the following API scopes:
  • read_orders — Orders and transactions
  • read_products — Products, variants, and collections
  • read_customers — Customer profiles
  • read_inventory — Inventory items and levels
  • read_locations — Store locations
  • read_reports — ShopifyQL reports

Skills for agents

Download Shopify skills file

Shopify connector documentation as plain markdown, for use in AI agent contexts.