Apps Script example · 10 min read

Fetch Shopify Orders into Google Sheets with Apps Script: Copy-Paste Apps Script Pattern

Working fetch shopify orders into google sheets with apps script example in Apps Script—copy-paste code, common mistakes, and when to get it built professionally.

UrlFetchAppShopify APIOrders

Shopify stores every order behind its Admin REST API, and pulling that data into a Google Sheet turns a merchant's order history into something a finance or fulfillment team can filter, pivot, and share without touching the Shopify admin panel.

This tutorial connects Apps Script to the Shopify Admin API using a private app access token, requests the most recent orders, and writes the results into an Orders tab with one batch write instead of dozens of individual row inserts.

The access token is read from Script Properties rather than hardcoded in the file, which keeps the credential out of version history and lets the same script move between a development store and a production store by swapping one property value.

By the end of this page you will have a fetchShopifyOrders function you can run manually, wire to a menu item, or schedule with a time-driven trigger so the Orders tab stays current without anyone re-running an export by hand.

Need this built? Hire a Google Apps Script developer →

Sheet / project setup

ConfigValuePurpose
SHOPIFY_STOREyour-store.myshopify.comShop domain
SHOPIFY_ACCESS_TOKENScript propertyAdmin API token
SheetOrdersid, name, total_price, created_at

What it does

The script issues a single GET request to the orders.json endpoint on the store's Admin API, requesting up to fifty orders at once, and maps each order object to a row of order ID, customer name, email, total price, financial status, and creation date.

Prerequisites

UrlFetchApp.fetch sends the request with the X-Shopify-Access-Token header attached, Shopify returns a JSON body containing an orders array, and the script parses that body with JSON.parse before transforming it into a plain array of arrays ready for setValues.

Walkthrough

Create a custom app in the Shopify admin, generate an Admin API access token scoped to read_orders, and store that token under the SHOPIFY_ACCESS_TOKEN key in Script Properties so the fetchShopifyOrders function can read it at runtime.

Edge cases

After validating that a token exists, the function builds the request URL from the store domain and API version, sends the fetch with muteHttpExceptions enabled so a failed request returns a response object instead of throwing, and only proceeds to write rows once the response code is 200.

Testing

A missing token throws immediately with a clear message, and a non-200 response throws with the raw response body attached so you can see whether Shopify rejected the token, the scope, or the API version without digging through execution logs.

Hardening

Run fetchShopifyOrders once against a development store first, confirm the Orders tab header row matches the six mapped fields, and only then point SHOPIFY_STORE at the production domain once the mapping has been verified by hand.

Variations

Shopify's REST Admin API enforces a bucket-based rate limit of roughly two requests per second, so a version of this script that pages through thousands of orders should add a short sleep between calls and follow the Link header for pagination instead of assuming one page is enough.

Full code: fetchShopifyOrders()

Store the access token in Script Properties before running fetchShopifyOrders, and confirm the Orders sheet exists or let the script create it.

var SHOPIFY_STORE = 'your-store.myshopify.com';
var SHOPIFY_TOKEN_PROPERTY = 'SHOPIFY_ACCESS_TOKEN';

function fetchShopifyOrders() {
  var token = PropertiesService.getScriptProperties().getProperty(SHOPIFY_TOKEN_PROPERTY);
  if (!token) throw new Error('Missing SHOPIFY_ACCESS_TOKEN script property.');

  var url = 'https://' + SHOPIFY_STORE + '/admin/api/2024-01/orders.json?status=any&limit=50';
  var options = {
    method: 'get',
    headers: { 'X-Shopify-Access-Token': token },
    muteHttpExceptions: true
  };

  var response = UrlFetchApp.fetch(url, options);
  if (response.getResponseCode() !== 200) {
    throw new Error('Shopify request failed: ' + response.getContentText());
  }

  var orders = JSON.parse(response.getContentText()).orders;
  var sheet = SpreadsheetApp.getActive().getSheetByName('Orders') || SpreadsheetApp.getActive().insertSheet('Orders');
  sheet.clearContents();
  sheet.appendRow(['Order ID', 'Name', 'Email', 'Total Price', 'Financial Status', 'Created At']);

  var rows = orders.map(function (order) {
    return [order.id, order.name, order.email, order.total_price, order.financial_status, order.created_at];
  });

  if (rows.length > 0) {
    sheet.getRange(2, 1, rows.length, rows[0].length).setValues(rows);
  }
}
  1. Line 5: Reads the access token from Script Properties instead of a hardcoded constant.
  2. Line 8: Builds the orders.json URL from the store domain and API version.
  3. Line 11: Attaches the required X-Shopify-Access-Token header.
  4. Line 16: Checks the response code before touching the body.
  5. Line 21: Gets or creates the Orders sheet so the script works on a first run.
  6. Line 30: Writes every row in one batched setValues call.

Deploy this example

  1. 01

    Open Apps Script

    In the bound spreadsheet: Extensions → Apps Script. For standalone projects, create one at script.google.com and link your Sheet by ID.

  2. 02

    Paste and save

    Add a .gs file, paste the code below, rename constants at the top (sheet names, column letters, API property keys), then save.

  3. 03

    Authorize once

    Run the main function from the editor. Accept OAuth scopes when prompted — triggers cannot run until authorization succeeds once.

  4. 04

    Add the trigger

    Triggers → Add trigger → choose the handler function and event (time-driven, on edit, or on form submit). Delete test triggers before production.

Before you run: fetch Shopify orders

  • 1Shopify custom app created with a read_orders scoped Admin API access token
  • 2Token saved under SHOPIFY_ACCESS_TOKEN in Script Properties, not in the code
  • 3SHOPIFY_STORE constant updated to the correct myshopify.com domain
  • 4Orders sheet exists or the script has permission to create it
  • 5First run tested against a development store
  • 6Response code checked before parsing the orders array
  • 7Pagination plan in place if order volume exceeds fifty per page

Frequently asked questions

Create a custom app under Settings > Apps and sales channels > Develop apps, configure the Admin API scopes you need (at minimum read_orders), install the app on the store, and copy the generated access token into Script Properties.

Script Properties keep the token out of the file contents, so it never appears in version history, copy-pasted templates, or shared Apps Script projects.

Shopify caps each page at 250 orders and returns a Link header with a next-page URL; this tutorial's code only reads the first page, so high-volume stores need to follow that header in a loop.

A rejected request still returns a JSON error body, and parsing it as if it were an orders array would throw a confusing TypeError instead of the clear authentication error Shopify actually sent.

Yes, the same pattern works against Shopify's draft_orders.json or fulfillments.json endpoints; only the URL path and the row-mapping function change.

Add a short Utilities.sleep call between paginated requests and watch the X-Shopify-Shopify-API-Call-Limit response header, which reports how many of your available request credits remain.

Related examples

Want this wired into your real workflow?

I adapt these patterns to your Sheet structure, APIs, and triggers — deployed in your Google account. Fixed-scope quotes from $500 · free 30-min consult · quote within 24 hours.