Pricing

How to Connect Shopify to Google Sheets

ShopifySaved SearchDateDocumentAmount07/01INV-40214,280.0007/02INV-40221,860.5007/05INV-40239,140.0007/08INV-40242,375.2507/09INV-40256,902.7507/12INV-40263,118.40BrookedABCDateDocumentAmount123456707/01INV-40214,280.0007/02INV-40221,860.5007/05INV-40239,140.0007/08INV-40242,375.2507/09INV-40256,902.7507/12INV-40263,118.40Google SheetsShopify report
JW
James Whitfield

Sync Shopify orders and products to Google Sheets, including the 60-day order window that silently hides your history and the GraphQL cost limit that throttles big pulls.

Shopify exports orders to CSV from the admin in about two minutes, which settles most one-off requests. If you need numbers that refresh, you are going through the Admin API, and there is one behaviour worth knowing before you start: by default the API only returns orders from the last 60 days, and it hides the rest silently rather than telling you. This guide covers the CSV route, the free GraphQL method with that scope problem solved, and the cost-based rate limiting that makes large pulls slow if you query carelessly.

The two-minute option: admin CSV export

In your Shopify admin go to Orders (or Products, or Customers), apply any filters you want, and click Export. Small exports download immediately; larger ones are emailed to you as a file, which can take a few minutes. Import the result into Sheets via File → Import.

One structural detail to expect: the orders export writes one row per line item, not per order. An order containing three products becomes three rows, with order-level fields such as the total repeated or left blank on the continuation rows. Summing the total column without deduplicating by order ID will overstate revenue, and this catches people every time.

Shopify to Google Sheets for free (Apps Script + GraphQL)

In your Shopify admin, go to Settings → Apps and sales channels → Develop apps, create an app, and configure its Admin API scopes. You want read_orders and read_products, and critically read_all_orders if you need anything older than 60 days. Install the app to reveal the Admin API access token, which begins shpat_.

Build on the GraphQL Admin API rather than REST. Shopify has made GraphQL the primary interface and has been retiring REST admin endpoints, so REST-based tutorials are on borrowed time. Pagination is cursor-based: ask for up to 250 records, read pageInfo.hasNextPage and pageInfo.endCursor, and pass that cursor as after on the next call.

Code.gs
function importShopifyOrders() {  const SHOP  = "your-store.myshopify.com";  const TOKEN = "shpat_XXXXXXXXXXXXXXXX";   // needs read_all_orders for history  const API   = "2026-07";                   // pin a version; do not use "latest"   const url = "https://" + SHOP + "/admin/api/" + API + "/graphql.json";  const rows = [];  let cursor = null;   // Request only the fields you need. Query cost scales with what you ask  // for, and a lean query drains the rate-limit bucket far more slowly.  const query = `    query Orders($cursor: String) {      orders(first: 250, after: $cursor, sortKey: CREATED_AT) {        pageInfo { hasNextPage endCursor }        nodes {          name          createdAt          displayFinancialStatus          customer { email }          currentTotalPriceSet { shopMoney { amount currencyCode } }        }      }    }`;   do {    const response = UrlFetchApp.fetch(url, {      method: "post",      contentType: "application/json",      headers: { "X-Shopify-Access-Token": TOKEN },      payload: JSON.stringify({ query: query, variables: { cursor: cursor } }),      muteHttpExceptions: true,    });     const body = JSON.parse(response.getContentText());    if (body.errors) throw new Error(JSON.stringify(body.errors));     const orders = body.data.orders;    orders.nodes.forEach((o) => {      rows.push([        o.name,        o.createdAt,        o.displayFinancialStatus,        o.customer ? o.customer.email : "",       // null for guest checkouts        o.currentTotalPriceSet.shopMoney.amount,        o.currentTotalPriceSet.shopMoney.currencyCode,      ]);    });     cursor = orders.pageInfo.hasNextPage ? orders.pageInfo.endCursor : null;    if (cursor) Utilities.sleep(500);   // let the cost bucket refill  } while (cursor);   const header = ["Order", "Created", "Status", "Email", "Total", "Currency"];  const ss = SpreadsheetApp.getActiveSpreadsheet();  const sheet = ss.getSheetByName("Orders") || ss.insertSheet("Orders");  sheet.clearContents();  sheet.getRange(1, 1, 1, header.length).setValues([header]);  if (rows.length) {    sheet.getRange(2, 1, rows.length, header.length).setValues(rows);  }}

Three details in that code worth spelling out. The API version is pinned: Shopify releases quarterly versions and drops support for old ones, so hard-coding a version means your script breaks on a date you choose rather than unpredictably. Money is returned as a MoneySet with separate shop and presentment currencies, which matters the moment you sell in more than one currency. And customer is null on guest checkouts, so reading o.customer.email directly throws on the first guest order in the result.

Limits: Apps Script's six-minute ceiling means a store with tens of thousands of orders needs the import chunked by date range across several runs. Rate limiting is cost-based rather than per-request, so the fix for throttling is usually to request fewer fields rather than to sleep longer.

The Brooked method

Brooked handles the cursor pagination, respects the cost budget so large stores import without tripping throttles, and flattens the nested money and customer objects into plain columns. Orders arrive one row per order, with line items available as a separate table, so revenue totals are correct without deduplication.

Step 1: Install Brooked

Install Brooked from the Google Workspace Marketplace. Free tier includes 100 imports per month, no credit card required.

Step 2: Connect Shopify

Choose Shopify in Brooked, enter your .myshopify.com domain and the Admin API access token from your custom app. If you plan to report on more than the last two months, make sure the app was granted read_all_orders before you install it, since adding the scope later requires reinstalling the app.

Step 3: Schedule the refresh

Set the import to re-run hourly, daily or weekly. Because it re-reads orders rather than listening for order-created webhooks, a scheduled refresh also picks up orders that were edited, refunded or cancelled after they were first placed, which append-on-webhook setups miss entirely.

BrookedBrooked AI, Shopify
Live
Ask anything about your Shopify data…

Method comparison

MethodCostSetupRefreshTwo-wayBest for
Shopify admin CSV exportFree2 minManual, emailed for large exportsNoA one-off orders or products dump
Apps Script + Admin GraphQL APIFree30 to 45 minTime-driven triggerDIYCustom fields, full control, no budget
Zapier / MakeFree tier limited · paid for volume10 to 20 minOn new orderNoAppending each new order as it happens
BrookedFree tier · Pro $29/user/mo~3 minScheduled (hourly, daily, weekly)YesScheduled reporting over full order history

Common use cases

  • Revenue reporting: daily sales by product, channel or region in a sheet finance already works from
  • Cohort analysis: measure repeat purchase rate and lifetime value across the full order history
  • Inventory planning: join stock levels against sales velocity to forecast reorder points
  • Ad attribution: combine Shopify orders with ad spend from other sources to compute true ROAS
  • Bulk price updates: edit prices in a sheet and write them back rather than clicking through the admin

Troubleshooting common issues

Frequently asked questions

Why can I only see the last 60 days of Shopify orders?

This is the single most surprising thing about the Shopify Admin API. By default an app can only read orders from the last 60 days, and older orders are simply absent from responses rather than raising an error, so it looks like your store lost its history. Access to everything older requires the read_all_orders scope, which you request in addition to the normal orders scope when configuring the app. Grant it, reinstall, and the full history appears.

Can I connect Shopify to Google Sheets for free?

Yes. Shopify's admin exports orders, products and customers to CSV at no cost, though anything large is emailed to you rather than downloaded directly. For refreshing data, the Apps Script method in this guide uses a free custom app access token and a free time-driven trigger. Brooked's free tier covers 100 imports a month if you would rather not maintain the script.

Should I use the REST or GraphQL Admin API?

GraphQL. Shopify has made the GraphQL Admin API the primary interface and has been retiring REST admin endpoints, with product and variant REST endpoints among the first to go. New integrations should be built on GraphQL, and older REST-based tutorials will progressively stop working.

How does Shopify's rate limiting work?

The GraphQL Admin API uses a cost-based leaky bucket rather than a simple request count. Each query costs points based on how much it returns, you hold a bucket of 1,000 points on standard plans, and it refills at 50 points a second. A query requesting many nested fields across many records costs far more than a lean one, so requesting fewer fields is the most effective way to speed up a large import.

How do I get more than 250 orders at a time?

250 is the maximum page size. Shopify uses cursor pagination: the response includes pageInfo with hasNextPage and endCursor, and you request the next page by passing that cursor in the after argument. There is no page number or offset, so you must follow the cursors in sequence rather than jumping ahead.

Can I write data from Google Sheets back to Shopify?

For editable fields, yes. Bulk price updates, inventory levels, tags and metafields can all be written back, and Brooked supports this. Some things are not writable: order line items cannot be edited after the fact, and financial totals are computed by Shopify from the line items rather than set directly.

Connect Shopify to Google Sheets today.

Free tier: 100 imports per month, no credit card required. Or see the full Shopify integration details.

Install Brooked free →

Also in eCommerce

More eCommerce guides

eCommerce

How to Connect WooCommerce to Google Sheets

Sync WooCommerce orders and products to Google Sheets via the REST API, including the permalink setting that 404s the whole API and the hosts that strip your auth header.

JW
James Whitfield
Read

Get your spreadsheet hours back

Brooked sets up in seconds. Your team is querying live data before lunch.

Get started free