ProductsDocsBlogConsultingAboutContactGet Started
Back to BlogSyncing Magento 2 Orders to Google Sheets in Real-Time
5 min readMageSheet Team

Syncing Magento 2 Orders to Google Sheets in Real-Time

Magento 2Google WorkspaceAutomationE-commerce

Hey everyone! Welcome to Pillar 2 of our B2B Automation series here at MageSheet.

For the past few posts, we've focused heavily on the Google Workspace side: building interfaces, handling auth, and setting up webhooks.

Now, it's time to connect the dots to one of the most powerful and complex e-commerce platforms on the market: Magento 2 (Adobe Commerce).

If your business runs on Magento, you know firsthand that getting data out of the platform for operational teams (like fulfillment, accounting, or B2B sales reps) can be a headache. Most companies rely on manual CSV exports at the end of the day, or pay hundreds of dollars a month for middleware SaaS connectors that constantly hit API limits.

Today, we're going to build a direct, blazing-fast, serverless bridge between Magento 2 and Google Sheets to sync orders the exact second they are placed.

The Architecture: Magento Webhook to Apps Script

We are going to use the doPost() architecture we discussed in our Apps Script Webhooks guide. The flow is simple:

  1. A customer clicks "Place Order" in Magento.
  2. Magento fires an internal event (sales_order_save_commit_after).
  3. Your Magento server sends a lightweight HTTP POST payload directly to a Google Apps Script URL.
  4. Google Apps Script parses the JSON and appends the order to a Google Sheet.

Notice what is missing here? No middleware. No API polling. No delays. It happens instantly.

Step 1: Prepping the Google Sheet Backend

First, let's create the destination. Open a new Google Sheet, name the first tab LiveOrders, and create the following headers in Row 1:

Magento Order IDStatusGrand TotalCustomer Email

Next, open Extensions > Apps Script and deploy the listener. We'll add some basic security here to ensure random bots don't fill your sheet with garbage data.

// Code.gs

// Define a secret key that only Magento and Apps Script know
const WEBHOOK_SECRET = "MageSheet_Super_Secret_2026"; 

function doPost(e) {
  try {
    const payload = JSON.parse(e.postData.contents);
    
    // Security check! Did Magento send the correct secret?
    if (payload.secret !== WEBHOOK_SECRET) {
      return ContentService.createTextOutput("Forbidden: Invalid Secret").setStatusCode(403);
    }
    
    // Parse the order data
    const order = payload.order_data;
    
    // Select the sheet and append
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("LiveOrders");
    sheet.appendRow([
      order.increment_id,
      order.status,
      order.grand_total,
      order.customer_email
    ]);
    
    return ContentService.createTextOutput(JSON.stringify({"status": "success"}))
      .setMimeType(ContentService.MimeType.JSON);
      
  } catch (error) {
    return ContentService.createTextOutput("Error: " + error.message).setStatusCode(500);
  }
}

Deploy this as a Web App (Execute as: Me, Access: Anyone). Copy the resulting URL.

Step 2: Firing the Event from Magento 2

While Magento 2 has robust REST and GraphQL APIs for pulling data, native "Outbound Webhooks" often require a small custom module.

To keep this tutorial lightweight, we will create a simple Observer module in Magento. Let's assume you have a custom module named MageSheet_GoogleSync.

You need an events.xml file in app/code/MageSheet/GoogleSync/etc/events.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_order_place_after">
        <observer name="magesheet_sync_order_to_google" instance="MageSheet\GoogleSync\Observer\SyncOrder" />
    </event>
</config>

And your Observer file app/code/MageSheet/GoogleSync/Observer/SyncOrder.php:

<?php
namespace MageSheet\GoogleSync\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\HTTP\Client\Curl;

class SyncOrder implements ObserverInterface
{
    private $curl;

    public function __construct(Curl $curl)
    {
        $this->curl = $curl;
    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $order = $observer->getEvent()->getOrder();
        
        // The URL you got from Google Apps Script
        $googleAppUrl = "https://script.google.com/macros/s/AKfycby..._aBCD/exec";
        
        // Prepare payload matching our Apps Script expectations
        $payload = [
            "secret" => "MageSheet_Super_Secret_2026",
            "order_data" => [
                "increment_id" => $order->getIncrementId(),
                "status" => $order->getStatus(),
                "grand_total" => $order->getGrandTotal(),
                "customer_email" => $order->getCustomerEmail()
            ]
        ];

        // Fire the cURL POST request
        $this->curl->addHeader("Content-Type", "application/json");
        $this->curl->post($googleAppUrl, json_encode($payload));
        
        // Important: Use asynchronous queues (RabbitMQ/Cron) in production
        // to prevent Google's response time from slowing down Magento checkout!
    }
}

The Crucial Production Warning: Asynchronous Queues

In the PHP example above, we placed a direct cURL request inside the sales_order_place_after event.

Warning: While this is great for a development test, doing this synchronously in production means your customer's browser will keep spinning on the checkout page until Google Apps Script replies. If Google is slow, your checkout is slow.

For enterprise environments, you MUST wrap that cURL request in a Magento Message Queue (RabbitMQ) or process it via a Cron job. This ensures that Magento instantly tells the customer "Order Success", while the actual HTTP request to Google happens a few seconds later in the background.

The Power of Instant Visibility

By utilizing this architecture, your Ops team can open Google Sheets and watch orders populate magically the second a B2B transaction is completed. From there, you can use Sheets formulas, Looker Studio dashboards, or Google Apps Script triggers to automatically forward that order to a 3PL or accounting department.

Further Reading

A Magento order-sync pipeline is only one pillar of a full Adobe Commerce automation stack. These companion posts cover the adjacent pieces most teams build next:

Building a resilient, enterprise-grade integration between Adobe Commerce and the Google Workspace ecosystem requires deep knowledge of Magento Message Queues, caching, and Apps Script quota limits. If your business needs a heavy-duty architecture designed for massive order volume, MageSheet specializes in exactly this. Get in touch!

Frequently Asked Questions

Why use webhooks instead of Magento's REST API polling for order sync?

Polling wastes cycles and adds latency. If you poll every 5 minutes, the average order takes 2.5 minutes to show up in your Sheet. Webhooks deliver in under 500ms because Magento pushes the event the instant it fires. You also eliminate API rate-limit risk — polling 12 times an hour across multiple endpoints burns through Magento's default throttle on busy stores. Webhooks are the correct production pattern.

What happens when Google Apps Script is down or returns an error?

Magento's webhook subscriber will retry with exponential backoff, but only for a limited number of attempts before dropping the event. The production-safe pattern is to have your Apps Script endpoint respond 200 OK immediately after appending to a raw intake sheet, then process the event in a background trigger. This decouples delivery from processing — if your enrichment logic breaks, you still have the raw event and can replay it later.

Does this work on Magento Open Source, Adobe Commerce Cloud, and on-prem equally?

Yes for all three, with small config differences. Open Source and on-prem need a custom module to emit the webhook (or an extension like Mageplaza Webhook). Adobe Commerce Cloud supports webhooks natively via the Extensibility framework in 2.4.6+. The Apps Script endpoint is identical in all three cases — what changes is only the Magento-side wiring.

How do I protect the webhook endpoint from being called by anyone with the URL?

Two layers: (1) Magento signs the webhook payload with an HMAC shared secret, and your doPost() function rejects any request whose signature does not match. (2) The Apps Script deployment uses 'Execute as: Me' plus a URL path secret so the endpoint is non-guessable. Never rely on the URL being secret alone — scanners find Apps Script webhook URLs within hours of deployment.

Is there a limit to how many orders per hour this pipeline can handle?

Apps Script has a 6-minute execution ceiling and roughly 90-second quota per individual URL fetch. In practice the sync handles 2,000-3,000 orders per hour comfortably. Past that, the pattern is to have the webhook write raw events into Google Sheets only, and then pull them into BigQuery on a schedule for heavy analytics — we cover that handoff in our Looker Studio article.

Stay Updated

Get the latest insights on AI, e-commerce, and Magento delivered to your inbox.