
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/admin→Store ID = [store]. - Start Date: The earliest record date to sync.
How to create a Custom App and generate an Access Token
How to create a Custom App and generate an Access Token
Follow these steps to create a custom app in Shopify and generate a long-lived (non-expiring) access token for Nekt:
Access the Dev Dashboard
- Log in to your Shopify store admin at
https://[your-store].myshopify.com/admin - Go to Settings > Apps
- Click Develop apps
- Click Build apps in Dev Dashboard to open the Dev Dashboard
Create a new Custom App
- In the Dev Dashboard, click Create app
- In the “Start from Dev Dashboard” section, enter a name for your app (e.g., “Nekt Data Integration”)
- Click Create
Configure your app version
- In the URLs section:
- Set your App URL to
https://shopify.dev/apps/default-app-home - Add
https://developers.google.com/oauthplaygroundas an Allowed redirection URL
- Set your App URL to
- Select a Webhooks API Version (use the latest stable version)
- In the Access section, enter the following scopes:
- Click Release
- Optionally enter a version name (e.g., “v1.0”) and message
- Click Release to confirm
Get your Client Credentials
- In the Dev Dashboard, go to your app’s Settings page
- Copy your Client ID and Client Secret
Open the Google OAuth Playground
Click the link below to open Google OAuth Playground pre-configured for Shopify:Open Shopify OAuth Playground →
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:
- Replace
SHOP_NAMEwith 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
- OAuth authorization endpoint:
- Replace
SHOPIFY_CLIENT_IDwith your Client ID - Replace
SHOPIFY_CLIENT_SECRETwith your Client Secret - Click Close
Authorize and Get Your Access Token
- Click Authorize APIs (Step 1 in the playground)
- You’ll be redirected to Shopify - click Install app to grant permissions
- After returning to the playground, click Exchange authorization code for tokens (Step 2)
- 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.
Managing Legacy Custom Apps (created before January 2026)
Managing Legacy Custom Apps (created before January 2026)
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:
Access Legacy Apps
- Go to Settings > Apps in your Shopify admin
- Find your app in the Legacy custom apps section
- Click on the app to manage its settings
View or Regenerate Access Token
- Go to the API credentials tab
- Click Reveal token once to view your access token
- Copy the token immediately - it’s only shown once
- 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.
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.
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.Streams and Fields
Below you’ll find all available data streams from Shopify and their corresponding fields:Orders
Orders
Stream containing orders, transactions and line items. Supports incremental sync using
updatedAt.Key Fields:id- Unique identifier for the ordername- The order name (e.g., #1001)legacyResourceId- Legacy numeric IDemail,phone- Contact informationprocessedAt,createdAt,updatedAt,cancelledAt,closedAt- Timestampsconfirmed- Whether the order is confirmedcurrencyCode,presentmentCurrencyCode- Currency codes
transactions[].id,kind,status,gateway,authorizationCode,test,paymentIdtransactions[].createdAt,processedAttransactions[].amountSet.presentmentMoney.amount,currencyCodetransactions[].amountSet.shopMoney.amount,currencyCodetransactions[].parentTransaction.id
totalPriceSet- Total price (shopMoney + presentmentMoney)subtotalPriceSet- Subtotal pricetotalShippingPriceSet- Total shippingtotalDiscountsSet- Total discountstotalTaxSet- Total taxtotalWeight,taxesIncluded,taxExempt
displayFinancialStatus- Financial status (PAID, PENDING, REFUNDED, etc.)displayFulfillmentStatus- Fulfillment status (FULFILLED, UNFULFILLED, PARTIAL, etc.)fullyPaid,fulfillable,restockable,test,customerAcceptsMarketingsourceName,sourceIdentifier,currentSubtotalLineItemsQuantitytags,note,clientIp
customer.id,firstName,lastName,emailshippingAddress.*- Full shipping addressbillingAddress.*- Full billing address
discountCode,discountCodes[]metafields[].id,namespace,key,value,type,description,createdAt,updatedAt
channelInformation.channelDefinition.handle
lineItems[].id,title,quantity,sku,vendor,variantTitlelineItems[].customAttributes[].key,valuelineItems[].discountedTotalSet.*,originalTotalSet.*lineItems[].discountAllocations[].allocatedAmount.amount,currencyCodelineItems[].discountAllocations[].discountApplication.targetType,allocationMethod,targetSelection,title,description,codelineItems[].variant.id,title,sku,product.id,product.title
Products
Products
Stream containing products, variants, images and metafields. Supports incremental sync using
updatedAt.Key Fields:id- Unique product identifiertitle- Product titledescriptionHtml- HTML descriptionvendor- Vendor nameproductType- Product type/categoryhandle- URL-friendly slugcreatedAt,updatedAt,publishedAt- Timestampsstatus- Product status (ACTIVE, ARCHIVED, DRAFT)tags- Product tagstemplateSuffix- Liquid template suffix
options[].id,name,position,values[]
variants[].id,title,sku,price,positionvariants[].inventoryPolicy- Inventory policy (DENY, CONTINUE)variants[].compareAtPrice- Original price before discountvariants[].createdAt,updatedAt,taxable,barcodevariants[].inventoryItem.id- Link to inventory item
images[].id,altText,originalSrcfeaturedImage.id,altText,originalSrc
metafields[].id,namespace,key,value,type,description
Inventory Items
Inventory Items
Stream containing inventory items, levels, and costing information. Supports incremental sync using
updatedAt.Key Fields:id- Unique inventory item IDlegacyResourceId- Legacy numeric IDsku- Stock keeping unittracked- Whether inventory is trackedtrackedEditable.reason- Why tracked field is editablerequiresShipping- Whether item requires shippingduplicateSkuCount- Count of duplicate SKUsinventoryHistoryUrl- URL to inventory historycreatedAt,updatedAt- Timestamps
countryCodeOfOrigin,provinceCodeOfOriginharmonizedSystemCodecountryHarmonizedSystemCodes[].countryCode,harmonizedSystemCode
inventoryLevels[].id- Inventory level IDinventoryLevels[].location.id,location.name- Location infoinventoryLevels[].item.id,item.sku- Item infoinventoryLevels[].quantities[].id,name,quantity,updatedAt- Quantity by type (available, committed, incoming, etc.)
unitCost.amount,unitCost.currencyCodemeasurement.weight.unit,measurement.weight.valuelocationsCount.count
variant.id,variant.title,variant.skuvariant.product.id,variant.product.title
Customers
Customers
Stream containing customer profiles. Supports incremental sync using
updatedAt.Key Fields:id- Unique customer IDfirstName,lastNamecreatedAt,updatedAtverifiedEmail,taxExempt,tags,statenumberOfOrders- Total order count
amountSpent.amount,amountSpent.currencyCodedefaultEmailAddress.emailAddress,defaultEmailAddress.marketingStatedefaultPhoneNumber.phoneNumber,defaultPhoneNumber.marketingState,defaultPhoneNumber.marketingCollectedFrom
addresses[].id,firstName,lastName,address1,city,province,country,zip,phone,name,provinceCode,countryCodeV2defaultAddress.*- Same structure as addresses
metafields[].id,namespace,key,value,type,description
Collections
Collections
Stream containing product collections and included products. Supports incremental sync using
updatedAt.Key Fields:id,title,handle,descriptionpublishedAt,updatedAt
image.altText,image.originalSrc
products[].id,title,handle,createdAt,updatedAtproducts[].productType,vendor,tags,totalInventory,status,price,inventoryQuantityproducts[].variants[].id,title,sku,price,inventoryQuantity
sortOrder,sortType,sortValue,templateSuffix,url
metafields[].id,namespace,key,value,type,description
Locations
Locations
Stream containing store and warehouse locations. Uses full table sync.Key Fields:
id,nameactive,activatable,deactivatable,deletablecreatedAt,updatedAt,deactivatedAtaddressVerified,isFulfillmentService
fulfillmentService.id,fulfillmentService.serviceName
address.address1,address2,city,country,countryCode,province,provinceCode,zip
metafields[].id,namespace,key,value,type,description
Abandoned Checkouts
Abandoned Checkouts
Stream containing abandoned checkouts. Uses full table sync.Key Fields:
id- Unique identifier for the abandoned checkoutabandonedCheckoutUrl- URL for the abandoned checkoutcreatedAt,updatedAt,completedAt- TimestampstaxesIncluded- Whether taxes are included
subtotalPriceSet.presentmentMoney.amount,currencyCodetotalPriceSet.presentmentMoney.amount,currencyCodetotalTaxSet.presentmentMoney.amount,currencyCodetotalDiscountSet.presentmentMoney.amount,currencyCode
customer.id,firstName,lastName,email,tags,state,note,createdAt,updatedAt
billingAddress.*- Address lines, city, province, country, zip, phoneshippingAddress.*- Address lines, city, province, country, zip, phone
lineItems[].id,title,sku,quantitylineItems[].variant.id,variant.price
discountCodes[]taxLines[].rate,title,priceSet.presentmentMoney.amount,currencyCode
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
SQL query
SQL query
- AWS
- GCP
Sample Result
Sample Result
| product_title | sku | variant_title | available_qty | committed_qty | incoming_qty | total_incoming_available | location_count | inventory_value | currency | stock_status |
|---|---|---|---|---|---|---|---|---|---|---|
| Classic White Tee | CWT-S | Small | 0 | 3 | 50 | 50 | 2 | 0.00 | USD | OUT_OF_STOCK |
| Denim Jacket | DJ-M | Medium | 2 | 8 | 0 | 2 | 1 | 89.98 | USD | LOW_STOCK |
| Canvas Sneakers | CS-42 | EU 42 | 4 | 1 | 20 | 24 | 3 | 159.96 | USD | LOW_STOCK |
| Leather Belt | LB-L | Large | 15 | 2 | 0 | 15 | 2 | 224.85 | USD | NORMAL |
| Summer Dress | SD-M | Medium | 47 | 5 | 0 | 47 | 2 | 1,551.00 | USD | HEALTHY |
| Basic Socks Pack | BSP-OS | One Size | 342 | 12 | 200 | 542 | 3 | 1,710.00 | USD | OVERSTOCK |
| Status | SKU Count | % of Catalog | Action |
|---|---|---|---|
| Healthy | 112 | 45% | No action needed |
| Normal | 62 | 25% | Monitor regularly |
| Low Stock | 38 | 15% | Plan reorder |
| Out of Stock | 20 | 8% | Urgent reorder |
| Overstock | 18 | 7% | Consider markdowns |
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
SQL query
SQL query
- AWS
- GCP
Sample Result
Sample Result
| product_title | sku | units_sold_30d | orders_30d | revenue_30d | daily_velocity | available_qty | days_of_stock | reorder_urgency |
|---|---|---|---|---|---|---|---|---|
| Classic White Tee | CWT-S | 89 | 76 | 2,225.00 | 2.97 | 0 | 0 | STOCKOUT |
| Denim Jacket | DJ-M | 42 | 38 | 3,318.00 | 1.40 | 2 | 1 | CRITICAL |
| Canvas Sneakers | CS-42 | 35 | 30 | 2,794.65 | 1.17 | 4 | 3 | CRITICAL |
| Leather Belt | LB-L | 28 | 25 | 839.72 | 0.93 | 15 | 16 | MONITOR |
| Summer Dress | SD-M | 18 | 15 | 1,079.82 | 0.60 | 47 | 78 | HEALTHY |
| Urgency | SKU Count | Avg Days of Stock | Revenue at Risk (30d) |
|---|---|---|---|
| STOCKOUT | 3 | 0 | $6,750.00 |
| CRITICAL (< 7 days) | 5 | 3 | $8,420.00 |
| REORDER NOW (7-14 days) | 8 | 11 | $4,230.00 |
| MONITOR (14-30 days) | 12 | 22 | $3,100.00 |
| HEALTHY (> 30 days) | 72 | 65 | — |
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
SQL query
SQL query
- AWS
- GCP
Sample Result
Sample Result
| location_name | unique_skus | total_available | total_committed | total_inventory_value | out_of_stock_skus | low_stock_skus | stockout_rate_pct |
|---|---|---|---|---|---|---|---|
| Main Warehouse - NYC | 248 | 12,450 | 892 | 187,250.00 | 8 | 14 | 3.2 |
| West Coast Fulfillment - LA | 195 | 8,320 | 645 | 124,800.00 | 12 | 22 | 6.2 |
| Pop-Up Store - Miami | 86 | 1,240 | 78 | 18,600.00 | 5 | 18 | 5.8 |
| Location | Inventory Value Share | Available Units Share | Stockout Rate |
|---|---|---|---|
| Main Warehouse - NYC | 56.6% | 56.5% | 3.2% |
| West Coast Fulfillment - LA | 37.7% | 37.8% | 6.2% |
| Pop-Up Store - Miami | 5.6% | 5.6% | 5.8% |
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
SQL query
SQL query
- AWS
- GCP
Sample Result
Sample Result
| product_title | sku | units_sold_90d | revenue_90d | available_qty | stock_value_at_cost | annual_turnover_rate | turnover_category |
|---|---|---|---|---|---|---|---|
| Vintage Scarf | VS-BLU | 0 | 0.00 | 85 | 1,275.00 | Dead Stock | |
| Wool Gloves | WG-M | 3 | 89.97 | 67 | 670.00 | 0.18 | Slow Mover |
| Leather Belt | LB-L | 28 | 839.72 | 15 | 224.85 | 7.47 | Moderate |
| Classic White Tee | CWT-M | 156 | 3,900.00 | 22 | 220.00 | 28.36 | Fast Mover |
| Canvas Sneakers | CS-42 | 35 | 2,794.65 | 4 | 159.96 | 35.00 | Fast Mover |
| Turnover Category | SKU Count | Stock Value ($) | % of Total Value | Recommended Action |
|---|---|---|---|---|
| Fast Movers (6x+/yr) | 24 | 12,400.00 | 15% | Increase safety stock |
| Moderate (2-6x/yr) | 48 | 24,800.00 | 30% | Maintain current levels |
| Slow Movers (< 2x/yr) | 35 | 20,650.00 | 25% | Reduce reorder quantities |
| Dead Stock (0 sales) | 18 | 24,750.00 | 30% | Markdown / bundle / discontinue |
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
SQL query
SQL query
- AWS
- GCP
Sample Result
Sample Result
| abandon_date | total_abandoned | recovered | recovery_rate_pct | total_cart_value | lost_revenue | recovered_revenue | avg_cart_value | avg_items_per_cart |
|---|---|---|---|---|---|---|---|---|
| 2026-01-27 | 34 | 6 | 17.6 | 4,892.50 | 4,032.00 | 860.50 | 143.90 | 2.4 |
| 2026-01-26 | 41 | 8 | 19.5 | 5,740.80 | 4,618.30 | 1,122.50 | 140.02 | 2.1 |
| 2026-01-25 | 28 | 4 | 14.3 | 3,980.20 | 3,410.00 | 570.20 | 142.15 | 2.6 |
| 2026-01-24 | 52 | 11 | 21.2 | 7,280.00 | 5,726.40 | 1,553.60 | 140.00 | 2.3 |
| 2026-01-23 | 38 | 7 | 18.4 | 5,320.60 | 4,342.10 | 978.50 | 140.02 | 2.2 |
| Metric | Value |
|---|---|
| Total Abandoned Carts | 193 |
| Total Cart Value | $27,214.10 |
| Lost Revenue | $22,128.80 |
| Recovered Revenue | $5,085.30 |
| Average Recovery Rate | 18.6% |
| Average Cart Value | $141.01 |
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
Incremental Sync
- Orders, Products, Inventory Items, Customers, and Collections support incremental sync using
updatedAt - Locations and Abandoned Checkouts 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) orCROSS 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 salecommitted— Units reserved for unfulfilled ordersincoming— Units expected from incoming transferson_hand— Total physical units at the location
- Filter by
nameto 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
shopMoneyfor internal reporting andpresentmentMoneyfor customer-facing analysis
API Scopes Required
The Shopify connector requires the following API scopes:read_orders— Orders and transactionsread_products— Products, variants, and collectionsread_customers— Customer profilesread_inventory— Inventory items and levelsread_locations— Store locations