Hourly Shopify orders sync to BigQuery

Every hour, stream new Shopify orders into a BigQuery table so your warehouse always has fresh sales data your analysts can query.

Deterministic Code
ShopifyGoogle BigQueryOperationsData Sync
PromptCreate

Every hour on the hour, list new Shopify orders created since the last successful run and stream them into a BigQuery table named shopify.orders_raw. This is a deterministic pipe from an ecommerce source into a warehouse — no reasoning, no drafting. Use a code workflow.

Cursor. Persist the highest updated_at seen so far in workflow state (fall back to the workflow start time on the very first run). On each run, call Shopify's List Orders with updated_at_min set to that cursor, status=any, and paginate through the Link header until there are no more pages. When the batch is done, update the cursor to the maximum updated_at across every order returned. Using updated_at instead of created_at means edits, cancellations, and refund state changes flow into the warehouse too.

Row shape. For each order, produce one flat row with these columns: order_id (integer), created_at (timestamp), customer_email (string), financial_status (string), fulfillment_status (string), subtotal (numeric), total (numeric), currency (string), line_item_count (integer), and line_items (JSON — the raw line_items array from the Shopify order). Shopify returns monetary amounts as strings, so parse subtotal_price and total_price to numeric before inserting. Preserve the whole line_items array as a JSON column so downstream SQL can unnest SKUs and quantities without another API round trip.

Insert. Send the mapped rows to BigQuery via Stream Insert Rows against dataset shopify, table orders_raw. Batch rows into chunks under BigQuery's 10 MB / 50,000 row per-request limit. Use the order_id as insertId so retries are naturally deduplicated by BigQuery's best-effort dedupe.

Row-level error handling — this is the whole point. Streaming inserts return HTTP 200 even when individual rows fail. Inspect insertErrors on every response. If it is empty or missing, all rows in that request succeeded. If any entry is present, do NOT advance the cursor, do NOT swallow the error — throw with the failing row indices and the BigQuery error messages so the run fails loudly and the operator sees it. Silently dropping orders is worse than a failed run.

Prerequisites the workflow assumes: the BigQuery dataset shopify exists in the target project, and the table orders_raw exists with a schema matching the row shape above (order_id INT64, created_at TIMESTAMP, customer_email STRING, financial_status STRING, fulfillment_status STRING, subtotal NUMERIC, total NUMERIC, currency STRING, line_item_count INT64, line_items JSON). Do not try to create the dataset or table inside this workflow.

Additional information

What does this prompt do?
  • Pulls every new or updated Shopify order each hour, so your warehouse stays within an hour of live sales data.
  • Flattens each order into a clean, queryable row (order id, customer email, status, totals, currency) with the full line item breakdown kept as JSON for deeper analysis.
  • Remembers exactly where the last run left off, so you never double-load an order and never miss one.
  • Fails the run loudly if BigQuery rejects any row, so silent data loss cannot creep into your reporting.
What do I need to use this?
  • A Shopify store you can connect with read access to orders.
  • A Google Cloud project with BigQuery enabled and permission to write to it.
  • A BigQuery dataset called shopify with an existing table named orders_raw that matches the row shape (order id, created at, customer email, financial status, fulfillment status, subtotal, total, currency, line item count, line items).
How can I customize it?
  • Change how often it runs — every 15 minutes for busier stores, every 4 hours if you don't need near-real-time data.
  • Point it at a different dataset or table name if your warehouse uses a different naming convention.
  • Add or remove columns in the row shape to match what your analysts actually query (for example, discount codes, tags, or shipping address).

Frequently asked questions

Will this back-fill my historical Shopify orders?
No. It starts from the moment you turn it on and moves forward from there. For historical data, run a one-time backfill separately, then let this workflow keep it fresh going forward.
What happens if an order is edited or refunded after it lands in the warehouse?
Because the workflow tracks the updated at timestamp, the changed order will flow through on the next hourly run as a fresh row. Your warehouse table becomes an append-only log — pick the latest row per order id in your queries to see the current state.
What if BigQuery rejects a row?
The run fails and surfaces the error, including which row was rejected and why. That way you can fix the schema, the data, or the credentials before the next run picks up where this one stopped. Nothing is silently dropped.
Do I need to create the BigQuery table first?
Yes. The workflow expects the shopify dataset and the orders_raw table to already exist, with a schema that matches the row shape described above. This keeps the workflow's job simple: load data, don't manage schemas.
Can I use a different warehouse like Snowflake or Redshift instead?
This specific workflow is built for BigQuery streaming inserts. If you use Snowflake or Redshift, ask the workflow builder to swap the load step for your warehouse of choice.

Stop patching together your ecommerce data pipeline.

Get fresh Shopify orders in BigQuery every hour, without paying a Fivetran-style connector bill.