Shopify to Airtable Order Integration

Created on September 12, 2024

python
async

This script demonstrates a simple integration between Shopify and Airtable, automatically syncing new orders from your Shopify store to an Airtable base. Each order is stored as a single row in Airtable, including order details, customer information, and a summary of products purchased.

Features

  • Listens for new order webhooks from Shopify
  • Fetches detailed order information from Shopify API
  • Creates a single row in Airtable for each new order

Prerequisites

  • A Shopify store with API access
  • An Airtable account and base set up

Shopify Access Token

Get your Shopify Access Token with the following API access scopes

  • read_orders
  • read_customers
  • read_products

Airtable API

Get your Airtable Personal Access Token with the following token permissions:

  • data.records:write
  • schema.bases:read

Others

  • Get your Airtable Base ID, this is the id of the base you want to send your orders to, it generally looks like this appXXXXXXXXXXXXXX
  • Airtable Table Name - this is a URL encoded table name (e.g., Test Table becomes Test%20Table)
  • Shopify Shop Name - this is the name of your Shopify store, you can get it from the url of your Shopify store (e.g., https://your-store-name.myshopify.com)

Configuration

  1. In your Airtable base, create a table named "Orders" with the following fields:

    • Order Number (Text)
    • Order Date (Date)
    • Total Price (Number)
    • Customer Name (Text)
    • Customer Email (Text)
    • Number of Products (Number)
    • Product SKUs and Quantities (Text)
  2. In your Shopify admin panel:

    • Go to Settings > Notifications
    • Scroll down to "Webhooks" and click "Create webhook"
    • Select "Order creation" as the event
    • Enter your server's URL as the webhook URL (This is the URL that you will get for running this function)

To Run This Function on Codeupify

  1. Import it into your account using the Import button at the top of this page
  2. Go into settings and modify the environment variables with your credentials
  3. Save the function
  4. Point the Shopify webhook to the Run URL on the info tab
  5. Finally, change the code as needed to get the data that you want

Function Code

import os
import requests
from datetime import datetime

SHOPIFY_ACCESS_TOKEN = os.environ.get('SHOPIFY_ACCESS_TOKEN')
SHOPIFY_SHOP_NAME = os.environ.get('SHOPIFY_SHOP_NAME')
SHOPIFY_API_VERSION = '2024-07'

AIRTABLE_PERSONAL_ACCESS_TOKEN = os.environ.get('AIRTABLE_PERSONAL_ACCESS_TOKEN')
AIRTABLE_BASE_ID = os.environ.get('AIRTABLE_BASE_ID')
AIRTABLE_TABLE_NAME = os.environ.get('AIRTABLE_TABLE_NAME', 'Orders')

def handler(request):
    payload = request['body']
    order_id = payload.get('id')

    shopify_url = f"https://{SHOPIFY_SHOP_NAME}.myshopify.com/admin/api/{SHOPIFY_API_VERSION}/orders/{order_id}.json"
    headers = {
        "X-Shopify-Access-Token": SHOPIFY_ACCESS_TOKEN,
        "Content-Type": "application/json"
    }
    shopify_response = requests.get(shopify_url, headers=headers)
    if not shopify_response.ok:
        raise requests.exceptions.RequestException(f"Shopify error: {shopify_response.status_code}, {shopify_response.text}")

    order = shopify_response.json()['order']

    product_count = len(order['line_items'])
    product_info = '|'.join(f"{item.get('sku', 'N/A')}:{item['quantity']}" for item in order['line_items'])

    airtable_data = {
        "fields": {
            "Order Number": str(order['order_number']),
            "Order Date": datetime.fromisoformat(order['created_at'].replace('Z', '+00:00')).strftime('%Y-%m-%d'),
            "Total Price": float(order['total_price']),
            "Customer Name": f"{order['customer']['first_name']} {order['customer']['last_name']}",
            "Customer Email": order['customer']['email'],
            "Number of Products": product_count,
            "Product SKUs and Quantities": product_info
        }
    }

    airtable_url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE_NAME}"
    headers = {
        "Authorization": f"Bearer {AIRTABLE_PERSONAL_ACCESS_TOKEN}",
        "Content-Type": "application/json"
    }
    airtable_response = requests.post(airtable_url, json=airtable_data, headers=headers)
    if not airtable_response.ok:
        raise requests.exceptions.RequestException(f"Airtable error: {airtable_response.status_code}, {airtable_response.text}")

    print("Processed Successfully")