=== OrderCarry Order Automation for WooCommerce ===
Contributors: houssemremili
Tags: woocommerce, google sheets, webhook, order export, automation
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 7.4
Requires Plugins: woocommerce
Stable tag: 1.0.3
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Automate WooCommerce orders with Google Sheets, webhooks, emails, custom rules and more.

== Description ==

Stop paying $30–$50 every month just to copy your orders into a spreadsheet.

OrderCarry runs inside your own WordPress site. When an order reaches the status you choose, it sends the details to Google Sheets, to any webhook URL, or as a custom email — automatically, in the background, without slowing down checkout.

**No task limits. No credits. No cloud account. No connection that expires.**

= Why people switch =

* Automation tools charge per task. This one does not count.
* Runs on your own server, so nothing disconnects and no token expires.
* Google Sheets setup takes about 60 seconds — no Google Cloud Console, no service account, no API keys.
* Smart Retry — if Google or your server hiccups, it tries again automatically. Configuration mistakes are reported instead of retried forever.
* One click **Send Test Order**, so you know it works before a real customer buys.
* Everything is logged in WooCommerce's own log viewer.

= What it does =

* **Google Sheets** — one row per order, created automatically, with headers. Google Sheets is a trademark of Google LLC; this plugin is not affiliated with or endorsed by Google.
* **Webhook** — the full order as JSON, signed with an `X-Ordsync-Signature` header. Works with Make, n8n, Zapier, Airtable, or your own backend.
* **Custom email** — your own subject and message, with `{order_number}`, `{customer_name}`, `{items}`, `{total}` and more.

= Built to not break your checkout =

Every automation runs in the background through Action Scheduler, the same queue WooCommerce uses itself. Your customer never waits for Google to answer.

= Works with your setup =

* WooCommerce HPOS (High-Performance Order Storage)
* The block-based checkout
* Multisite
* PHP 7.4 through 8.3

= Free vs Pro =

The free version is not a demo. It sends unlimited orders to as many Google Sheets, webhooks and email addresses as you like, with full retry and logging — reliability is never the paid part.

OrderCarry Pro is a separate download and adds:

* **PDF invoices** — generated per order and attached to the email.
* **Conditional rules** — "only orders over €100", "only this shipping country", "only this payment method".
* **Bulk import** — push your existing orders into a sheet in one go.

Pro comes with a 14-day free trial, no credit card required.

== Installation ==

This guide assumes you have never done any of this before. Every step says
exactly what to click.

= Before you start =

* WooCommerce must already be installed and active.
* WordPress 6.4 or newer, PHP 7.4 or newer.
* For Google Sheets you need a normal Google account. You do **not** need a
  Google Cloud account, a credit card, or an API key.

= Step 1: Install the plugin =

From your WordPress admin:

1. Go to **Plugins → Add Plugin**.
2. Search for **OrderCarry**.
3. Click **Install Now**, then **Activate**.

If you downloaded a ZIP file instead:

1. Go to **Plugins → Add Plugin → Upload Plugin**.
2. Choose the ZIP file, click **Install Now**, then **Activate**.

= Step 2: Open the settings =

Go to **WooCommerce → OrderCarry** in the left menu.

You will see four tabs:

* **Google Sheets** — one row per order in a spreadsheet.
* **Webhook** — the full order as JSON, for Make, n8n, Zapier, or your own system.
* **Custom Email** — your own email, to yourself or to the customer.
* **Logs** — what was sent, and what failed.

You can use one tab, or all of them. Set up whichever you need. Each tab works
on its own.

= Step 3: Send orders to Google Sheets =

**First, create the sheet and its script.**

1. In the **Google Sheets** tab, click **Where do I get this URL?**. The
   instructions open up, with a script already prepared for you.
2. Click **Create a blank Google Sheet**. A new spreadsheet opens in Google.
   (If you already have a sheet you want to use, open that one instead.)
3. In that Google sheet, click **Extensions** in the top menu, then
   **Apps Script**. A code editor opens in a new tab.
4. Delete everything you see in that editor. It usually contains a few lines
   like `function myFunction() {}`. Remove all of it.
5. Go back to the OrderCarry tab in WordPress and click **Copy script**.
6. Go back to the Apps Script editor and paste (Ctrl+V, or Cmd+V on a Mac).
7. Click the save icon (the floppy disk), or press Ctrl+S.

**Now publish the script so your shop can reach it.**

8. In the Apps Script editor, click the blue **Deploy** button (top right),
   then **New deployment**.
9. Click the gear icon next to "Select type" and choose **Web app**.
10. Set **Execute as** to **Me**.
11. Set **Who has access** to **Anyone**. This sounds unsafe, but it is not:
    the script only accepts requests that carry your secret, which is already
    inside the script you pasted.
12. Click **Deploy**. Google will ask you to authorise the script the first
    time. Click through the permission screens. If you see a warning that the
    app is not verified, click **Advanced**, then **Go to (your project)**.
    It is your own script — you are trusting yourself.
13. Google now shows a **Web app URL** that ends in `/exec`. Copy it.

**Finally, tell the plugin about it.**

14. Back in WordPress, paste that URL into **Google Sheet web app URL**.
15. Switch the toggle to **ON**.
16. Choose when orders should be sent under
    **Send orders when they become** (see the explanation further down).
17. Click **Save changes**.
18. Click **Send test order**.

Within a few seconds a test row should appear in your Google sheet, and the
plugin should show a green success message. The column headers are created
automatically the first time.

= Step 4: Send orders to a webhook =

Use this if you want the order data in Make, n8n, Zapier, Airtable, an ERP, or
your own application.

1. Open the **Webhook** tab.
2. Paste the address that should receive the orders into **URL**. It must
   start with `https://`.
3. Switch the toggle to **ON**.
4. Choose when orders should be sent under **Send orders when they become**.
5. Click **Save changes**, then **Send test order**.

Your receiving system should get a JSON message containing the order.

Every request also carries a header called `X-Ordsync-Signature`. This is
proof that the request really came from your shop and not from someone else.
If the system on the other end supports it, use that header to verify the
request. You will find the signing key under **Advanced → Verifying that a
request really came from your shop**.

If you just want to try it out first, create a free test address at
webhook.site, paste it in, and press **Send test order**. You will see the
order arrive.

= Step 5: Send an email for every order =

1. Open the **Custom Email** tab.
2. In **Send to**, type the email address that should receive the message.
   Type the single word `customer` instead if you want it sent to the buyer.
3. Write the **Subject**.
4. Write the **Message**.
5. Switch the toggle to **ON**, click **Save changes**, then
   **Send test order**.

In the subject and the message you can use variables. They are replaced with
the real values of each order:

`{order_number}` `{status}` `{date}` `{customer_name}` `{customer_email}`
`{customer_phone}` `{items}` `{total}` `{currency}` `{store_name}`
`{coupons}` `{shipping_method}` `{transaction_id}` `{order_note}`

For example, a subject of `New order {order_number} - {total}` arrives as
"New order 1042 - 59.90".

The full list is always shown under the message box, so you do not have to
remember it.

= Understanding "Send orders when they become" =

This decides **when** an order is sent. It is the setting people get wrong
most often.

* **Processing** — the usual choice. The order is sent once the customer has
  paid.
* **Completed** — sent when you mark the order as finished.
* **Any status** — sent as soon as the order is created, whatever happens
  next.

Important: if you take **bank transfer, invoice, or cash on delivery**, those
orders often never become "Processing". They go from pending straight to
on-hold or completed. If you choose Processing, those orders are never sent
and you will think the plugin is broken. Choose **Any status** instead.

Each destination has its own setting. Your sheet can use Processing while your
webhook uses Any status.

= Step 6: Check that it is working =

Place a real test order in your shop, or change an existing order to the
status you selected.

Then open the **Logs** tab. You will see each attempt, whether it succeeded,
and the error message if it failed.

The coloured label at the top right of each destination also tells you the
state at a glance:

* **Sent ... ago** — real orders are arriving. This is what you want.
* **Test passed — no orders yet** — the connection works, but no real order
  has been sent yet.
* **Last attempt failed** — something is wrong. Hover over it to see why.
* **Nothing sent yet** — not used yet.

= If something does not work =

**Nothing arrives at all.** Check the trigger status first, as described
above. Bank transfer orders and Processing are the most common cause.

**The Google sheet stays empty.** Make sure you set "Who has access" to
**Anyone** when deploying. If you changed the script afterwards, you must
deploy again: **Deploy → Manage deployments → edit → New version**. A URL that
ends in `/dev` will not work; it must end in `/exec`.

**Emails do not arrive.** This is almost never the plugin. WordPress itself
often cannot send email on cheap hosting. Install any SMTP plugin, configure
it, and try again.

**The row appears a minute later, not instantly.** That is normal and
deliberate. Orders are sent in the background so your checkout is never slowed
down or blocked by a slow connection.

**You want to see what is queued.** Open **Advanced → View the queue**.

== Frequently Asked Questions ==

= Do I need a Google Cloud account? =

No. You paste a short script into your own Google Sheet and deploy it as a web app. That takes about a minute and costs nothing.

= Is there a limit on how many orders it can send? =

No. It runs on your server, so there is nothing to meter.

= Will it slow down my checkout? =

No. Orders are queued and sent in the background through Action Scheduler.

= How long until the row appears? =

Usually a minute or two, sometimes longer on a very quiet store.

WordPress only runs background jobs when someone visits the site, so a busy shop syncs almost straight away while a shop with no visitors waits until the next visit. Nothing is ever lost — the order stays in the queue until it runs, and you can watch it under **WooCommerce → Status → Scheduled Actions**.

The **Send Test Order** button skips the queue and fires immediately, which is why it feels instant.

If you need every order synced within seconds regardless of traffic, ask your host to enable a real system cron and disable WP-Cron.

= Does it work with HPOS? =

Yes. OrderCarry declares full compatibility with High-Performance Order Storage and stores its state on the order itself, so it works with either storage mode.

= My emails are not arriving. =

That is almost always your web host blocking outgoing mail, not the plugin. Install any free SMTP plugin and it will work.

= Where do I see errors? =

**WooCommerce → Status → Logs**, source `order-sync`. Also reachable from the Logs tab in the plugin.

= Does it send my data anywhere I did not ask for? =

No. Order data only goes to destinations you enable and addresses you type in yourself. See the "External services" section below for the full list.

== External services ==

This plugin sends order data to services **you configure yourself**. Nothing is sent anywhere until you enable a destination and enter a URL.

* **Google Apps Script** — if you enable the Google Sheets destination, order data (order number, date, status, customer name, email, phone, billing and shipping address, items, totals, payment method and customer note) is sent to the web app URL you provide, inside your own Google account. Sent once per order when that order reaches your chosen status, and when you click Send Test Order. Google's terms: https://policies.google.com/terms — Google's privacy policy: https://policies.google.com/privacy

* **Your own webhook URL** — if you enable the webhook destination, the same order data is sent as JSON to the address you enter. You choose the recipient, so the applicable terms are that service's own.

* **Freemius** — the plugin uses the Freemius SDK for licensing, updates and (optionally) usage tracking. In the free version nothing is sent until you click "Allow & Continue" on the opt-in screen; choosing "Skip" leaves the plugin fully functional and silent. If you opt in, or if you buy a licence, your site URL, WordPress and PHP version, and your email address are sent to Freemius to activate and validate the licence. Freemius terms: https://freemius.com/terms/ — Freemius privacy policy: https://freemius.com/privacy/

No order data is ever sent to the plugin author.

== Screenshots ==

1. Step 1 — paste one script into your own Google Sheet. No Google Cloud account, no API keys.
2. Step 2 and 3 — paste the URL, switch the destination on, then Send Test Order and get the answer immediately.
3. Webhook destination — full order JSON, signed with an X-Ordsync-Signature header.
4. Custom email — your own subject and message, with {variables} filled in from the order.
5. Orders arriving as rows in a Google Sheet, headers created automatically.

== Changelog ==

= 1.0.3 =
* Every install now runs as many Google Sheets, webhook and email destinations as it is configured with.
* Translations are no longer loaded by hand; WordPress handles them for hosted plugins.

= 1.0.0 =
* First release: Google Sheets, Webhook and Custom Email destinations, background processing through Action Scheduler, smart retry, signed webhooks, Send Test Order and a log viewer.

== Upgrade Notice ==

= 1.0.0 =
First release.
