# Publish from a Google Sheet with n8n

You write posts in a Google Sheet. n8n reads each row, publishes it to your channels through MADIAD
Hub, and writes the result back to that same row.

**You need:** an n8n (self-hosted or n8n Cloud), a MADIAD Hub API key (every plan includes one), and
a Google account.

---

## What is in the pack

| File | What it does | Needed? |
|---|---|---|
| `wf-01-publish-on-schedule.json` | Scans the sheet every 15 minutes and publishes rows marked `Publish now` | **Yes** |
| `wf-03-reconcile.json` | Checks posts the platform is still processing and writes the real outcome | **Yes** |
| `wf-02-publish-at.json` | Publishes at the time in the `Publish At` column | if you schedule |
| `wf-04-usage.json` | Logs your quota to the `Usage` tab every morning | recommended |
| `wf-06-retry-unpublish.json` | Runs the `Retry` and `Unpublish` actions | if needed |
| `wf-05-publish-now.json` | Publishes immediately instead of waiting for the next scan | optional |
| `Gate.gs` | Script you paste into the sheet; adds the MADIAD Hub menu. Goes with `wf-05` | only with `wf-05` |

> **Why `wf-03` is required:** many platforms accept a post first and process it later, so when
> `wf-01` finishes, the post is only queued. Without `wf-03` that row stays on `Publishing` forever,
> even though the post went out.

---

## Part A. Connect the sheet to n8n (15 minutes)

### Step 1. Copy the sample sheet

**Why:** you need a sheet of your own for the workflows to write into. The original is view-only.

Open the sample sheet and choose **File › Make a copy**.

### Step 2. Fill in the Config tab

**Why:** it tells the workflows which of your profiles to publish with.

1. The **Config** tab is in the tab bar at the bottom of the sheet, next to `Schedule`.
2. Paste your `profile_id` into the `Value` column on the `profile_id` row. You find it in the
   MADIAD Hub dashboard, under **Connections**.
3. If you publish to Pinterest, also fill in `pinterest_board_id`.

![The Config tab in the bottom tab bar, and the Value cell of the profile_id row](https://hub.madiad.com/n8n-templates/guide/tu-dang/g-cau-hinh.png)

### Step 3. Store the API key in n8n

**Why:** n8n calls MADIAD Hub as you. The key lives in n8n, not in the sheet, because sheet links
get passed around.

Open the **MADIAD Hub** node, click **Connect to Header Auth**, then:

1. **Name:** `Authorization`
2. **Value:** `Bearer ` (with the space) followed by your API key, from the dashboard under API keys.
3. Click **Save**.

The other workflows pick this same credential. Create a key just for n8n: if it leaks, you revoke
that one key and nothing else stops.

### Step 4. Import the workflows and pick your sheet

**Why:** every Google Sheets node has to know which copy to read and write.

1. In n8n: **Workflows › Import from File**, choose `wf-01`, then `wf-03`. Those two at minimum.
2. Open each node that shows a red triangle. Click **Connect to Google Sheets** to sign in to
   Google, then pick your copy of the sheet in **Document**.

### Step 5. Publish

**Why:** a workflow only runs on its own once it is published. Until then nothing happens, and
nothing reports an error either.

When no red triangle is left, click **Publish** at the top right. Do it for each workflow.

After Part A, any row whose `Action` is `Publish now` goes out within 15 minutes.

---

## Part B. Publish the moment you ask (optional, 10 minutes)

This adds a **MADIAD Hub** menu to the sheet and, if you want, publishes as soon as you edit a cell,
instead of waiting for the 15-minute scan.

### Step 6. Copy the Production URL of wf-05

**Why:** it is the address the sheet calls in n8n.

1. Import `wf-05-publish-now.json`, pick your sheet and publish it, as in steps 4 and 5.
2. Open the **Command from the sheet** node, choose **Production URL** and copy it.

The right address contains `/webhook/`. One with `/webhook-test/` is the Test URL: it only works
while you have n8n open and are listening for a test event.

### Step 7. Paste Gate.gs into Apps Script and save

**Why:** it adds the MADIAD Hub menu to the sheet.

1. In the sheet: **Extensions › Apps Script**.
2. Delete the code that is there and paste all of `Gate.gs` from the pack.
3. Click **Save**. **You do not need Deploy.**

![Extensions menu, Apps Script item](https://hub.madiad.com/n8n-templates/guide/tu-dang/g-apps-script-menu.png)

![Apps Script editor: Save, and Deploy is not needed](https://hub.madiad.com/n8n-templates/guide/tu-dang/g-apps-script-luu.png)

### Step 8. Set WEBHOOK_URL

**Why:** it tells the script where to send commands.

In Apps Script: **Project Settings** (the gear on the left) › **Script Properties** › add a property
named `WEBHOOK_URL` whose value is the Production URL you copied, then **Save script properties**.

![Script Properties: WEBHOOK_URL with the Production URL, then save](https://hub.madiad.com/n8n-templates/guide/tu-dang/g-thuoc-tinh.png)

### Step 9. Reload the sheet and test the connection

**Why:** proves the sheet can reach n8n before you publish anything for real.

1. Reload the sheet. A **MADIAD Hub** menu appears next to **Help**. No menu means the script was
   not pasted or not saved.
2. Run **MADIAD Hub › Test n8n connection** and approve the permission prompt the first time.
   "Reached n8n" means the sheet reached n8n. It publishes nothing and does not check the workflow's
   nodes: errors on the n8n side (no sheet picked, wrong key) show in the Executions tab, step 11.

![The MADIAD Hub menu next to Help, Test n8n connection item](https://hub.madiad.com/n8n-templates/guide/tu-dang/g-menu.png)

### Step 10. Add the trigger so editing a cell publishes

**Why:** setting `Action` to `Publish now` sends the row straight away, without the menu.

1. In Apps Script, click the **clock** icon (Triggers) on the left › **Add Trigger**.
2. Function: `onEditInstallable`. Event source: **From spreadsheet**. Event type: **On edit**. Save,
   and approve the permission prompt.

![Add Trigger dialog: onEditInstallable, From spreadsheet, On edit, Save](https://hub.madiad.com/n8n-templates/guide/tu-dang/g-trigger.png)

Skip this step and you can still publish at once: select the rows, then
**MADIAD Hub › Publish selected rows now**.

### Step 11. Try one post and check the result

**Why:** you see one post make the whole trip, from the sheet to the channel.

1. On a row that has a `Caption` and `Channels`, set `Action` to `Publish now`. A new row with no
   `Post ID` yet is fine: the workflow writes the id.
2. The sheet shows "Sent 1 publish command(s)". A few seconds later `Status` turns `Publishing`,
   then `Published` with the post link.
3. Nothing changes? Open the workflow in n8n, **Executions** tab. A red run failed: open it to see
   which node broke and why.

---

## Day to day

Write from **row 3**. Row 1 is the header, row 2 explains each column. Do not delete either.

| Column | What you put in it |
|---|---|
| `Action` | `Publish now` · `Schedule` · `Retry` · `Unpublish` |
| `Channels` | pick one, or type several separated by commas |
| `Title` | optional, a separate title for YouTube and Pinterest. Empty means the `Caption` is used |
| `Caption` | the body of the post |
| `Media` | image or video URL starting with `https://`. One link per line for several images |
| `Publish At` | only with `Schedule`. Format `2026-09-10 08:30` |
| `First Comment` | optional, posted straight under the post |

**Reddit** cannot be published from this sheet yet: Reddit needs a subreddit, and the sheet has no
column for it. On a profile that already has Reddit connected, write Reddit posts in the MADIAD Hub
dashboard.

Everything else is written by the workflow; leave it alone. `Publishing` means sent and waiting for
the platform. `Published` appears only once the platform has actually published. A failed row
explains itself in `Error`: fix it, clear `Status`, set `Action` again.

---

## Facebook Pages, LinkedIn and other channels

- **Facebook, LinkedIn:** one connection is one account, and that account can manage several Pages.
  The profile can publish to all of them.
- **TikTok, Instagram** and other channels you sign in to with their own account: one account per
  profile.
- **Choosing the Page per post:** write the post in the MADIAD Hub dashboard and pick the Page there.
  This works while the profile has no Page pinned.
- **With a Page pinned** (dashboard, Connections): posts go to that Page. A post aimed at another
  Page is refused; unpin first to publish elsewhere.
- **Posts from this sheet** go to the pinned Page, because the sheet has no Page column. If the
  account manages several Pages, pin the one you want. To choose the Page per row, contact MADIAD.

---

## The MADIAD Hub node for n8n (optional)

Use the MADIAD Hub node instead of the HTTP Request node: it has a profile picker filled from your
account, and a **Test** button that tells you whether the key works before you run anything.

- **Self-hosted n8n:** go to **Settings › Community nodes**, click **Install a community node**, enter
  `n8n-nodes-madiad-hub`, tick the consent box, **Install**. Or `npm install` that package in
  `~/.n8n`, then restart n8n.
- **n8n Cloud:** only installs nodes n8n has verified, and this one is not verified yet. On Cloud, use
  the JSON workflows above: they only need built-in nodes.

The node and the workflows share one API key.

---

## The pack is updated regularly

New versions always live at <https://hub.madiad.com/n8n-templates>. Download and re-import over the
old workflows in n8n. When `Gate.gs` changes, paste it over the old file in Apps Script and save:
the trigger you added stays in place.

Your sheet is not touched. If a release renames a column, this section will say so, because a
renamed column is the one change that makes a workflow lose track of your existing data.

## When something does not work

| What you see | Usual cause |
|---|---|
| No MADIAD Hub menu | `Gate.gs` not pasted or not saved, then reload the sheet (steps 7, 9) |
| The menu says "No rows to publish" | The row lacks `Caption` or `Channels`, or you selected row 1 or 2 |
| The menu says a row was not sent because of `Action` | Set `Action` to `Publish now` |
| Test connection returns 404 | The Test URL (`/webhook-test/`) was pasted, or the workflow is not published |
| Editing a cell does nothing | The trigger from step 10 is missing |
| n8n says `Parameter "Document" is required` | A Google Sheets node has no sheet picked (step 4) |
| Runs fine, publishes nothing | `Status` is not empty, or `Action` does not match exactly |
| `The Channels cell matches no platform` | A typo in a channel name. Pick from the list instead |
| `Media links must start with https://` | A Drive sharing link. You need a direct file URL |
| A row stuck on `Publishing` | `wf-03` is not published |
| Posted to the wrong Facebook Page | Pin the right Page in the dashboard, under Connections |
| `401` or `403` | Wrong API key, missing `Bearer `, or the plan has expired |
| The MADIAD Hub node does not appear | n8n has not restarted, or you are on n8n Cloud |

Full API documentation: <https://docs.madiad.com>
