Shopify Loader
The Shopify loader pulls e-commerce data from your Shopify store into your data warehouse. It uses Shopify’s Admin REST API and GraphQL API, and supports incremental sync via the updated_at timestamp for most resources.
Prerequisites
- A Shopify store (any plan, including development stores)
- A Shopify user with Admin or Staff access (with appropriate permissions)
- A connected Warehouse (target warehouse) with write permissions on the target schema
Authentication
The Shopify loader uses OAuth 2.0 for authentication.
OAuth 2.0 Setup
- In SignalSmith, click Add Loader and select Shopify
- Enter your Shopify store domain (e.g.,
mystore.myshopify.com) - Click Connect with Shopify
- You’ll be redirected to your Shopify admin to install the SignalSmith app
- Review the requested permissions and click Install app
- You’ll be redirected back to SignalSmith with the connection established
SignalSmith requests the following access scopes:
| Scope | Purpose |
|---|---|
read_orders | Access order, fulfillment, and refund data |
read_products | Access product, variant, and collection data |
read_customers | Access customer records |
read_inventory | Access inventory levels and locations |
read_analytics | Access store analytics data |
read_marketing_events | Access marketing event data |
All scopes are read-only. SignalSmith never modifies data in your Shopify store.
Store Domain
Enter your Shopify store’s .myshopify.com domain, not your custom domain. For example, if your store is at shop.mycompany.com, use mycompany.myshopify.com.
Available Objects
| Object | API Name | Description | Default Sync Mode |
|---|---|---|---|
| Orders | orders | Orders with line items, discounts, shipping, and payment details | Incremental |
| Products | products | Product catalog with title, description, and tags | Incremental |
| Product Variants | variants | Individual product variants (size, color) with SKU, price, and inventory | Incremental |
| Customers | customers | Customer records with contact info, order history, and tags | Incremental |
| Collections | collections | Product collections (smart and custom) | Full Refresh |
| Inventory Items | inventory_items | Inventory records tied to variants | Incremental |
| Inventory Levels | inventory_levels | Stock quantities per variant per location | Full Refresh |
| Locations | locations | Store locations, fulfillment centers, and warehouses | Full Refresh |
| Fulfillments | fulfillments | Shipment records tied to orders | Incremental |
| Refunds | refunds | Refund records with line items and amounts | Incremental |
| Transactions | transactions | Payment transactions associated with orders | Incremental |
| Discount Codes | discount_codes | Discount code definitions | Full Refresh |
| Abandoned Checkouts | checkouts | Abandoned checkout sessions | Incremental |
Orders and Line Items
Orders are extracted with their line items in a parent-child relationship. The orders table contains order-level data (totals, customer, shipping address), while a separate order_line_items table contains one row per item in the order. Join these on order_id.
Financial details included per order:
| Field | Description |
|---|---|
subtotal_price | Sum of line item prices before taxes and shipping |
total_tax | Total tax amount |
total_shipping | Shipping charges |
total_discounts | Total discount amount applied |
total_price | Final price charged to the customer |
currency | Order currency code (e.g., USD, EUR) |
Customer Data
Customer records include:
- Contact information (email, phone)
- Default address
- Order count and total spent (lifetime)
- Tags and notes
- Marketing consent status
- Account status (enabled, disabled, invited)
Configuration
| Setting | Description | Default |
|---|---|---|
| Store Domain | Your .myshopify.com domain | — (required) |
| Objects | List of objects to sync | — (you choose during setup) |
| Sync Mode | Full Refresh or Incremental (per object) | Incremental |
| Cursor Field | Field used for incremental sync | updated_at |
| Primary Key | Field(s) that uniquely identify a record | id |
| Include Archived Orders | Whether to sync cancelled/archived orders | true |
| Target Schema | Warehouse schema for Shopify tables | — (required) |
| Table Prefix | Optional prefix for table names | shopify_ |
| Schedule | Sync frequency | Hourly |
Scheduling Notes
- Rate limits: Shopify’s API uses a leaky bucket rate limiter. Standard plans allow 2 requests per second; Shopify Plus allows higher limits. SignalSmith manages rate limiting automatically with backoff and credit tracking.
- GraphQL cost limits: For high-volume stores, SignalSmith uses the GraphQL Admin API, which has a cost-based rate limit (1,000 points per second). Complex queries consume more points. SignalSmith optimizes queries to minimize cost.
- Order volume: High-volume stores may have millions of orders. The initial backfill can take several hours. Subsequent incremental syncs are much faster.
- Deleted records: Shopify’s API does not include permanently deleted records in list endpoints. Deleted products and customers are not captured by incremental sync. Run periodic full refreshes if you need to detect deletions.
- Multi-currency: If your store uses Shopify Payments with multi-currency, order amounts are stored in the customer’s presentment currency. The
presentment_currencyandshop_currencyfields help with conversion.
Schema Mapping
Shopify field types are mapped to warehouse-compatible types:
| Shopify Type | Warehouse Type | Notes |
|---|---|---|
string | VARCHAR | |
integer | BIGINT | IDs, counts |
decimal | DOUBLE | Monetary amounts (already in currency units, not cents) |
boolean | BOOLEAN | |
datetime | TIMESTAMP | UTC normalized from ISO 8601 |
array | JSON / VARCHAR | Tags (comma-separated), line items |
object | JSON / VARCHAR | Nested structures like addresses, shipping lines |
Monetary Values
Unlike Stripe, Shopify returns monetary values in standard currency units (e.g., 29.99 for $29.99), not cents. No division is needed in your models.
Troubleshooting
| Issue | Solution |
|---|---|
| ”401 Unauthorized” | The app may have been uninstalled from Shopify. Reconnect from the loader settings |
| ”403 Forbidden” on specific resources | The app may lack the required access scope. Reconnect to re-request permissions |
| ”429 Too Many Requests” | SignalSmith handles rate limits automatically. If persistent, reduce the number of objects synced simultaneously |
| Missing recent orders | Incremental sync uses updated_at. Very recent orders may appear on the next run |
| Inventory levels are stale | Inventory levels use Full Refresh mode. Increase sync frequency if real-time accuracy is needed |
| Line items missing from orders | Line items are in a separate table (order_line_items). Join on order_id |
| Customer data missing for orders | Some orders may be from guest checkouts without a customer record. Check for null customer_id values |
| Product variants not appearing | Variants are a separate object from products. Ensure you’ve selected “Product Variants” in addition to “Products” |
Next Steps
- Create a model to transform your raw Shopify data
- Build customer lifetime value models by joining customers, orders, and transactions
- Build audiences based on purchase behavior