How to Auto-Save Gmail Attachments to Google Drive and Google Sheets

How to Auto-Save Gmail Attachments to Google Drive and Google Sheets

Does your inbox accumulate decks, invoices, and reports from clients& and you spend time each week manually saving them to Drive and updating a spreadsheet? This guide shows you how to build an automation in n8n that watches your Gmail inbox, saves every incoming attachment to a Google Drive folder, and logs the file name, size, sender, and a direct link to a Google Sheets spreadsheet — all without you lifting a finger.

✄ Skip the build: If you just want the ready-made workflow with Setup and Credentials Guides, download it here.

WHat You’ll Build

The completed workflow is a 5-node pipeline that runs every minute:

Gmail Trigger
    |
    v [check has attachment]
IF Node
    |   \
    |    [No] *stop*
    v
Upload to Google Drive
    |
    v
Format Log Entry (Code node)
    |
    v
Log to Google Sheets

Prerequisites

  • An n8n instance (self-hosted or n8n Cloud)
  • A Gmail account (Google Workspace or personal)
  • A Google Drive folder to store attachments
  • A Google Sheets spreadsheet with headers: Date Received, Sender, Subject, File Name, File Size, Google Drive Link, Status
  • OAuth2 credentials configured in n8n for Gmail, Google Drive, and Google Sheets

Step 1: Set Up the Gmail Trigger

Add a Gmail Trigger node. This is the entry point that polls your inbox on a schedule.

Configuration

  • Poll times: Set to every minute (or adjust to reduce API usage)
  • Filter : Label IDs: INBOX
  • Read status: unread
  • Has attachment: true
  • Options ‘ Download attachments: enabled
  • Attachment prefix: attachment_

Sample output

{
  "from": "client@example.com",
  "subject": "Q3 Report",
  "date": "2025-07-10T14:24:00Z",
  ...
}
--- binary
{
  "attachment_0": {
    "mimeType": "application/pdf",
    "fileName": "q3-report.pdf",
    "fileExtension": "pdf",
    "fileSize": 245760
  }
}
⚢ Note: The trigger will only pick up emails arriving after you activate the workflow. Emails that arrived earlier will not be processed.

Step 2: Check for Attachment Data with an IF Node

Even with the filter enabled on the trigger, it is safe practice to confirm that binary attachment data exists before trying to upload anything. Add an IF node after the trigger.

Condition

Set the condition to test whether the $binary object has at least one key:

Left value:  ={{ Object.keys($binary).length > 0 }}
Operator:  equals (boolean)
Right value: true

The True output branch continues to the Drive upload step. The False branch is left unconnected, which means those items silently stop processing.

Step 3: Upload to Google Drive

Add a Google Drive node and set it to upload mode. This node will save the attachment binary data directly to your Drive folder.

Configuration

  • Operation: Upload
  • File name: ={{ $binary.attachment_0.fileName }}
  • Drive: My Drive
  • Folder: Paste your Drive folder ID
  • Input data field name: attachment_0

Sample output

{
  "id": "1ABCDEFGH_examplefileid",
  "name": "q3-report.pdf",
  "mimeType": "application/pdf",
  "size": "245760",
  "webViewLink": "https://drive.google.com/file/d/1ABCDEFGH_examplefileid/view"
}

Step 4: Format the Log Entry with a Code Node

The Gmail Trigger and the Google Drive node each produce their own data structures. Use a Code node to merge them into a single clean row.

Code

const email = $('Gmail Trigger').item.json;
const driveFile = $('Upload to Google Drive').item.json;

return {
  json: {
    date_received: email.date
      ? new Date(email.date).toLocaleString('en-US', { timeZone: 'America/Chicago' })
      : new Date().toLocaleString('en-US'),
    sender:        email.from || '(unknown sender)',
    subject:       email.subject || '(No Subject)',
    file_name:     driveFile.name || '(unnamed file)',
    file_size_kb:  driveFile.size
      ? Math.round(parseInt(driveFile.size) / 1024) + ' KB'
      : 'N/A',
    drive_link:    `https://drive.google.com/file/d/${driveFile.id}/view`,
    status:        'Saved'
  }
};
✄ Tip: The code references the Gmail Trigger node by name using $('Gmail Trigger'). If you rename either node, update this reference to match.

Step 5: Log to Google Sheets

Add a Google Sheets node and set it to Append Row mode.

Column mapping

Sheet column n8n expression
Date Received ={{ $json.date_received }}
Sender ={{ $json.sender }}
Subject ={{ $json.subject }}
File Name ={{ $json.file_name }}
File Size ={{ $json.file_size_kb }}
Google Drive Link ={{ $json.drive_link }}
Status ={{ $json.status }}

Full System Flow Diagram

Here is what the entire pipeline looks like end-to-end:

[Inbox]           [Inbox]    [Inbox]
   | new email with attachment
   v
[Gmail Trigger]    ------------------- every minute
   |
   v  Has binary data?
[IFNODE]
   | Yes    *stop* (No)
   v
[Google Drive Upload]  -------- POST file to folder
   | receives file ID & metadata
   v
[Code Node]  ----------------- merges email + drive data
   |
   v
[Google Sheets Append]  ------- APPENDs 1 row
   |
   v
[Done]

Testing the Workflow

With the workflow saved, run a manual test:

  1. Click Test workflow in n8n.
  2. Send yourself an email with a PDF or image attachment.
  3. Wait a few seconds for the trigger to pick it up.
  4. Confirm the file appears in your Drive folder.
  5. Check your Sheets spreadsheet for a new row with all 7 columns populated.

FAQ

Will this pick up emails that arrived before I activated the workflow?

No. The Gmail Trigger only processes new emails arriving after the workflow is activated. To backfill old emails you would need a separate batch processing step.

What happens if an email has multiple attachments?

This workflow processes only attachment_0 (first attachment) by default. To handle multiple attachments, you can add a Split In Batches node that iterates over Object.keys($binary).

Can I filter by sender or subject?

Absolutely. Add another condition to the IF node — for example {{ $json.from.includes('@example.com') }} — or use Gmail’s built-in search filters on the trigger node itself.

Will files get duplicated?

Only if the same message is picked up twice, which should not happen under normal operation. The Gmail Trigger uses a watermark to track which messages it has already seen.

Can I save to a specific Drive sub-folder based on sender or file type?

Yes. Use a Switch node before the Drive upload to route based on $json.from or $binary.attachment_0.mimeType, and set a different folder ID in each branch.

What happens if the Drive upload fails?

n8n will retry the workflow run according to your instance’s error retry settings. You can also add an Error Workflow in n8n to send an alert email or Slack message if things go wrong.

Save Yourself the Build Time

Get the fully configured workflow JSON + Setup Guide + Credentials Guide in one download. Import it into n8n in minutes.

Get the Workflow Pack $14.99

What’s Next

Nice work! You have a fully operational Gmail automation that saves and logs attachments without any manual intervention. Here are some way to extend it:

  • Notifications: Add a Slack or Telegram node at the end for real-time alerts in Drive or Sheets.
  • File type routing: Use a Switch node to sort PDFs, XLSX, and images into separate Drive sub-folders.
  • Spreadsheet processing: After saving, parse XLSX files with the ReadBinaryFile node and extract data into your Sheets.
  • Archiving: Add a cron node that moves old files to an archive folder once a month.

Tags: n8n workflow, Gmail automation, Google Drive automation, Google Sheets automation, auto-save email attachments, n8n Gmail trigger, file pipeline automation, no-code email file management

How to Build an AI Social Media Manager Bot with n8n

How to Build an AI Social Media Manager Bot with n8n (Powered by Telegram)

Keeping your social media channels active is a full-time job — and most founders, creators, and small teams simply don’t have the bandwidth to do it consistently. What if you could send a voice note, a document, or a quick text to a Telegram bot and have it draft, get your approval, and publish a polished post to X and LinkedIn automatically?

That’s exactly what this n8n workflow builds: your own AI-powered social media manager, running 24/7 inside Telegram, connected to Google Gemini for smart content generation, and wired directly to your X (Twitter) and LinkedIn profiles.

Prefer to skip the setup? Grab the ready-made template → and be up and running in under 10 minutes.

What You’ll Build

  1. Send a text, voice note, or document to your Telegram bot — the AI understands all three formats
  2. The agent drafts a platform-appropriate post, respecting X’s 280-character limit and LinkedIn’s professional tone
  3. You review the draft in Telegram and approve it — nothing gets published without your explicit say-so
  4. With your approval, the bot publishes instantly to X (Twitter) and/or LinkedIn
  5. The bot remembers your brand voice, company details, and preferences over time — you stop repeating yourself in every session

How It Works — The Big Picture

The workflow uses a Telegram bot as the command center. Every incoming message is classified by type — text, document, voice, or button tap — and routed through the right processing pipeline before reaching a Google Gemini-powered AI Agent. The agent drafts posts, manages both short- and long-term memory, and uses LinkedIn and X tools to publish only after you approve.

┌──────────────────────────────────────────────────────────────────────┐
│  AI SMM MANAGER                                                      │
│                                                                      │
│  [Telegram Trigger] → [Set Context] → [Input Type Switch]            │
│                                              │                       │
│         ┌────────────────────────────────────┼────────────────┐      │
│         ↓                ↓                   ↓                ↓      │
│     [Text]          [Document]            [Voice]        [Callback]  │
│         │           ↓ Download           ↓ Download           │      │
│         │           ↓ Encode             ↓ Encode        [If cm?]   │
│         │           ↓ Gemini OCR         ↓ Transcribe   ↓       ↓   │
│         │           ↓ Doc Prompt         ↓ Audio Prompt [Clear] [✗]  │
│         └───────────┴────────────────────┘                          │
│                               ↓                                      │
│                         [AI Agent] ←── [Gemini LLM]                 │
│                    ↑   ↑   ↑   ↑      [Short-term Memory]           │
│                    │   │   │   └── [Retrieve Knowledge (vector)]     │
│                    │   │   └──── [Save Knowledge (sub-workflow)]     │
│                    │   └──────── [Create X (Twitter) Post]           │
│                    └──────────── [Create LinkedIn Post]              │
│                               ↓                                      │
│                    [Split Response] → [Split Out]                    │
│                               ↓                                      │
│                    [Send Response via Telegram]                      │
└──────────────────────────────────────────────────────────────────────┘
  

What You’ll Need

  • n8n (cloud or self-hosted, version 1.0+)
  • Telegram Bot API key — create one for free via @BotFather in Telegram
  • Google AI Studio API key — free at aistudio.google.com (powers Gemini 2.0 Flash)
  • X (Twitter) Developer API — free developer account at developer.x.com
  • LinkedIn OAuth credentials — create an app at the LinkedIn Developer Portal
  • A companion n8n sub-workflow — “Save Vector Store Record” (included in the template pack) for long-term memory storage

Estimated build time: 45–60 minutes from scratch, or under 10 minutes with the template.


Part 1 — Bot Entrance and Input Preprocessing

1 Telegram Trigger (telegramTrigger)

This is the entry point. The Telegram Trigger node opens a webhook that listens for all incoming events from your bot — text messages, documents, voice notes, and inline button taps.

Configuration:

  1. Open the node and click “Credential for Telegram API”
  2. Paste your BotFather token and save
  3. Under “Updates”, enable: message, callback_query, inline_query, and *
{
  "message": {
    "chat": { "id": 198472651, "type": "private", "first_name": "Sarah" },
    "text": "Write a LinkedIn post about our product launch next Tuesday",
    "message_id": 142
  },
  "update_id": 553043001
}
💡

Tip: Add a “Restrict to chat IDs” filter so only your account can trigger the bot. Find your personal chat ID by messaging @userinfobot on Telegram.

2 Set Input Context (set)

This node normalizes the raw Telegram payload into clean, consistently named fields — regardless of whether the input is a text message, a file, or a voice note.

FieldWhat it capturesExample
chat_idSender’s chat ID (from message or callback)198472651
message_textText content of the message"Write a post about our launch"
update_typeDetected type: text, document, voice, callback"text"
file_idDocument file ID (if document sent)"BQACAgIA..."
file_mime_typeMIME type of document"application/pdf"
file_captionCaption text sent with the document"Our company overview"
voice_file_idVoice note file ID"AwACAgIA..."

3 Input Type Switch (switch)

Routes execution to the correct processing branch based on update_type:

  • text → straight to AI Agent via Text Prompt
  • document → Download → Encode → Gemini OCR → Document Prompt → AI Agent
  • voice → Download → Encode → Gemini Transcribe → Audio Prompt → AI Agent
  • callback → If node (checks whether it’s a memory-clear command)

Part 2 — Document and Audio Processing

4 Document Branch (Download → Encode → Describe)

When a user sends a PDF, presentation, or any file, three nodes work in sequence. Download document fetches the raw binary from Telegram using the file_id. Encode document converts the binary to base64. Describe document sends it to Gemini 2.0 Flash via HTTP POST:

{
  "contents": [{
    "parts": [
      { "text": "Extract all the information about the company or product from this document" },
      {
        "inline_data": {
          "mime_type": "application/pdf",
          "data": "JVBERi0xLjQgJeL..."
        }
      }
    ]
  }]
}

Gemini returns a structured extraction of all company and product details, which gets injected into the AI Agent prompt alongside the document’s caption.

💡

Tip: This works with PDFs, HTML files, Word docs, and most common formats. The mime_type is pulled automatically from Telegram’s download metadata.

5 Voice Branch (Download → Encode → Transcribe)

Voice messages follow the same pattern — Download Audio → Encode Audio → call Gemini with “Generate a transcript of the speech.” The transcript becomes the chatInput field, so the agent processes it exactly like a typed message.

📌

Note: Telegram encodes all voice messages as OGG files. The workflow hardcodes "mime_type": "audio/ogg" in the Gemini request — do not change this value.


Part 3 — The AI Agent

6 AI Agent (agent)

The brain of the entire operation. The agent receives the normalized user input and decides autonomously what to do next: ask clarifying questions if context is missing, draft a post tailored to the target platform, send it to you for review, publish after your explicit approval, or save brand information to long-term memory.

The system message enforces a strict rule: nothing gets published without the user’s explicit “approved” signal. This is the safety net that keeps the bot from acting without consent.

ToolPurpose
Retrieve knowledgeFetches relevant brand context from the vector store
Save knowledgeCalls the sub-workflow to save new information to vector memory
Create X (Twitter) postPosts to X; enforces the 280-character limit
Create post in LinkedIn as a personPosts from your personal LinkedIn profile
Create post in LinkedIn as a companyPosts from a company/organization page

7 Google Gemini Chat Model + Memory

The agent is powered by Google Gemini via the lmChatGoogleGemini node. Two memory systems work in parallel:

Short-term memory (Buffer Window Memory): Keyed to the chat_id, this stores recent conversation history so the agent maintains context within a single Telegram session.

Long-term memory (In-Memory Vector Store + Gemini Embeddings): Powered by the embedding-001 model, this lets the agent remember brand voice, company info, and preferences across completely separate sessions.

💡

Tip: The in-memory vector store resets when n8n restarts. For production use, replace it with a persistent store like Pinecone, Supabase pgvector, or Qdrant.

8 Memory Clear Callback

When a user taps an inline Telegram button with callback data "cm", the workflow routes to the If node, clears all buffer window memory via Chat Memory Manager, and sends a “Memory is cleaned” confirmation back to Telegram. Handy for switching between clients or starting fresh on a new campaign.


Part 4 — Response Delivery

9 Split + Send (code + telegram)

Telegram enforces a 4,096-character limit per message. The Split agent’s response node uses JavaScript to break the AI output into 3,000-character chunks, and Split Out iterates over each chunk. Every chunk is sent as a separate Telegram message so nothing is ever truncated.

function splitString(str, size) {
  let result = [];
  for (let i = 0; i < str.length; i += size) {
    result.push(str.slice(i, i + size));
  }
  return result;
}

for (const item of $input.all()) {
  const parts = splitString(item.json.output, 3000);
  item.json.parts = parts;
}

return $input.all();

Full System Flow

User sends message (text / voice / document) to Telegram bot
                          │
                          ▼
              [Telegram Trigger] → [Set Input Context]
                                            │
               ┌────────────────────────────┼───────────────────┐
               ▼                            ▼                   ▼
         [text route]               [document route]     [voice route]
               │                    ↓ Download            ↓ Download
               │                    ↓ Encode (base64)     ↓ Encode (base64)
               │                    ↓ Gemini OCR           ↓ Gemini Transcribe
               │                    ↓ Document Prompt      ↓ Audio Prompt
               └────────────────────┴──────────────────────┘
                                            │
                                            ▼
                                      [AI Agent]
                            ┌─────────────────────────┐
                            ↓                         ↓
                    [X & LinkedIn Tools]    [Memory: Save + Retrieve]
                            └─────────────────────────┘
                                            │
                                            ▼
                              [Split Response (3,000 chars)]
                                            │
                                            ▼
                              [Send each chunk via Telegram]
                                            │
                                            ▼
                                      User gets reply ✓
  

Testing Your Workflow

  1. Import the JSON and attach all credentials (see the Credentials Guide PDF)
  2. Activate the workflow — n8n registers the Telegram webhook automatically
  3. Open Telegram, find your bot, and send: "Write a LinkedIn post about how AI is changing small business marketing"
  4. Confirm the bot replies with a draft and asks for your approval
  5. Reply "approved" — check your LinkedIn profile for the published post
  6. Test a voice note: record 10 seconds describing a product feature and send it to the bot
  7. Test document processing: send a PDF of your company overview and ask the bot to write a post about it
ProblemLikely CauseFix
Bot doesn't respond at allWorkflow not activeToggle the Active switch in n8n
"Forbidden" error posting to XTweet exceeds 280 charactersThe agent handles this — rephrase your brief to be shorter
Document not processedUnsupported mime typeStick to PDF, HTML, or DOCX formats
Memory lost after restartIn-memory vector store clearedSwitch to Pinecone or Qdrant for persistent memory
LinkedIn post failsOAuth token expiredRe-authorize LinkedIn credentials in n8n settings
No response from botGemini API quota exceededCheck your AI Studio usage dashboard and upgrade if needed

Frequently Asked Questions

Can I add more platforms like Instagram or Facebook?

Yes — n8n has native nodes for Facebook Pages and Instagram Business. Add them as additional tool nodes attached to the AI Agent, following the same pattern as the X and LinkedIn tools already in this workflow.

Does the bot ever post without my approval?

Never. The system message explicitly instructs the agent to always get explicit user approval before posting anything. The draft is always sent to Telegram first, and you can review, edit, or reject it before anything goes live.

Can I use this for multiple clients or brands?

The workflow is keyed by chat_id, so each Telegram conversation has separate memory. For multiple brands, create separate Telegram bots and run separate workflow instances — or extend the memory key to include a brand identifier prefix.

What happens if Gemini is unavailable?

The AI Agent node will throw an error and n8n will log it. For production use, add a retry setting (3 attempts, 5-second delay) on the AI Agent node and an error handler that sends you a fallback Telegram message so you know something went wrong.

Is my document content safe when processed through Gemini?

Your document data is sent to Google's API for processing. Review Google AI Studio's data usage policy at aistudio.google.com if confidentiality is a concern. For sensitive documents, consider replacing the Gemini HTTP calls with a self-hosted model via Ollama.

How do I teach the bot my brand voice?

Just tell it in plain language: "My company is Acme Corp, we sell B2B SaaS to HR teams, and our tone is professional but approachable." The Save Knowledge tool stores this automatically and the bot recalls it in all future sessions without you needing to repeat it.

🚀 Get the AI SMM Manager Template

Everything you need to deploy your own Telegram-powered social media bot: ready-to-import workflow JSON, Setup Guide PDF, and full Credentials Guide PDF — go from download to live bot in under 10 minutes.

Get the Template →

Instant download · Works on n8n Cloud and self-hosted

What's Next?

  • Add Instagram support via the Instagram Graph API as a new tool on the AI Agent node
  • Schedule posts by connecting a Google Sheets queue and a Schedule Trigger to batch-publish at optimal times
  • Add AI image generation using DALL-E or Flux to auto-create visuals for each post before publishing
  • Multi-language support — instruct the agent to detect the user's language and draft posts in the same language automatically
  • Analytics tracking — connect a Google Sheets node to log every post with timestamps so you can track what's performing
n8n Telegram Google Gemini LinkedIn Twitter / X AI Agent Social Media automation

How to create viral shorts automation

Creating viral short-form videos by hand takes hours — filming, editing, writing captions, uploading. This n8n viral shorts automation replaces every manual step. First, you add a subject to a Google Sheet. Next, the workflow generates a hyper-realistic AI image with Kie AI, turns it into a motion video using Google Veo 3, writes an optimized YouTube title and hashtags with Claude AI, and publishes the final video directly to your YouTube channel. As a result, you get a fully automated content pipeline that runs without you touching a single tool.

Prefer to skip the build? Grab the ready-made template and start publishing AI shorts in under 15 minutes.

What You Will Build

  1. You add a subject keyword to a Google Sheet row with Status set to pending — for example, rusted wrench.
  2. An AI agent generates a detailed image prompt: a hyper-realistic macro photo of the rusted object with a hand holding a spray bottle, foam reacting on contact.
  3. A second AI agent turns that image prompt into a video prompt describing the full transformation sequence — rusted to clean chrome in 6 to 9 seconds.
  4. Kie AI generates the image, then uses it as a reference frame to generate the video with Google Veo 3 at 9:16 aspect ratio.
  5. Claude AI writes a YouTube title (under 46 characters) and five hashtags optimized for the subject.
  6. The video binary is downloaded, uploaded to YouTube as a public Short, and added to your playlist.
  7. The Google Sheet row updates to Video Published with the exact publish timestamp.

How This n8n Viral Shorts Automation Works

The workflow uses two parallel polling loops to handle AI generation reliably. Image generation and video generation both take time — sometimes 30 seconds, sometimes several minutes. Instead of timing out, each loop checks the API status every 30 seconds and routes on the result: success moves forward, still generating loops back, and failure writes an error to the sheet.

┌────────────────────────────────────────────────────────────────────┐ │ N8N VIRAL SHORTS AUTOMATION │ │ │ │ [Manual Trigger] │ │ │ │ │ ▼ │ │ [Google Sheets: Get pending row] │ │ │ │ │ ▼ │ │ [AI Agent: Image Prompt] ←── OpenRouter Chat Model │ │ │ │ │ ▼ │ │ [AI Agent: Video Prompt] ←── OpenRouter Chat Model 1 │ │ │ │ │ ▼ │ │ [Kie AI: Generate Image] ── POST /jobs/createTask │ │ │ │ │ ┌─────▼──────────────────────────────────────────┐ │ │ │ IMAGE POLLING LOOP (every 30s) │ │ │ │ [Get Image URL] → [Switch2] │ │ │ │ success → [Update row: Image URL] │ │ │ │ waiting → [Wait 30s] → loop │ │ │ │ generating → [Wait 30s] → loop │ │ │ │ fail → [Update IMG status: Failed] │ │ │ └────────────────────────────────────────────────┘ │ │ │ (success only) │ │ ▼ │ │ [Kie AI: Generate Video] ── POST /veo/generate (Veo3 Fast) │ │ │ │ │ ┌─────▼──────────────────────────────────────────┐ │ │ │ VIDEO POLLING LOOP (every 30s) │ │ │ │ [Get Video] → [Switch] │ │ │ │ successFlag=1 → [Update Video Url] │ │ │ │ successFlag=0 → [Wait 30s] → loop │ │ │ │ successFlag=2 → [Wait 30s] → loop │ │ │ │ successFlag=3 → [Update Video status: Failed]│ │ │ └────────────────────────────────────────────────┘ │ │ │ (success only) │ │ ▼ │ │ [OpenRouter: Generate caption + hashtags] │ │ │ │ │ ▼ │ │ [Code: Separate Title from Hashtags] │ │ │ │ │ ▼ │ │ [Google Sheets: Update Video Title + Hashtags] │ │ │ │ │ ▼ │ │ [HTTP Request: Download video binary] │ │ │ │ │ ▼ │ │ [YouTube: Upload video] → [Wait 10s] → [Add to Playlist] │ │ │ │ │ ▼ │ │ [Google Sheets: Update Youtube Status + timestamp] │ └────────────────────────────────────────────────────────────────────┘

What You Will Need

  • n8n — self-hosted or n8n Cloud (v1.30+). See the n8n hosting documentation for setup options.
  • Kie AI account — for image generation (nano-banana-pro model) and video generation (Veo3 Fast). See the Kie AI API documentation.
  • OpenRouter account — to call Claude 3.7 Sonnet for prompt generation and caption writing.
  • Google Sheets — one spreadsheet with the 7-column schema shown below.
  • YouTube channel — with a YouTube Data API v3 OAuth2 credential and a playlist ID to publish into.
  • Google account — connected in n8n via OAuth2 for Google Sheets access.

Estimated build time: 60 minutes from scratch, or under 15 minutes with the ready-made template.

Part 1 — Picking the Subject and Generating Prompts

Step 1 — Manual Trigger and Get Pending Row

The workflow starts with a Manual Trigger — you click Execute in n8n when you want to publish a new Short. First, it reads the Google Sheet and finds the first row where Status = pending. That row contains one field: objects — a plain text subject like rusty bolt, corroded pipe fitting, or old iron padlock. This single word drives everything that follows.

// Google Sheets row — what the workflow reads
{
  "row_number": 3,
  "objects": "rusted wrench",
  "Image url": "",
  "Video Url": "",
  "Status": "pending",
  "Video Title": "",
  "Video Hashtags": "",
  "Youtube Status": ""
}

Tip: You can batch-add subjects to the sheet in advance. The workflow picks exactly one row per execution, so running it once per day keeps a steady publishing cadence without any extra configuration.

Step 2 — Image Prompt Agent

The first AI Agent node receives the object name and generates a detailed image prompt. The system prompt enforces a very specific visual style: ultra-realistic macro photography, a rusted object with thick orange corrosion, one adult human hand holding a clear plastic spray bottle with blue liquid, the trigger actively pressed, and a foam reaction forming where the spray hits. These constraints are non-negotiable in the prompt — they exist to produce consistent, high-quality results that look real rather than generated.

For example, given the input rusted wrench, the agent returns a prompt like:

Ultra-realistic macro photograph of an extremely rusted adjustable wrench on a concrete 
workshop floor. Natural daylight, shallow depth of field. Thick orange corrosion, deep 
pitted metal surface, rust flakes visible. One realistic adult human hand holding a clear 
plastic spray bottle with blue cleaning liquid. Trigger spray head visible, finger pressing 
trigger, spray stream connected from nozzle to wrench surface. White-blue foam building on 
contact. Hyper-realistic 4K, cinematic macro shot. No logos, no text.

Step 3 — Video Prompt Agent

The second AI Agent takes the image prompt as input and generates a video prompt. The video prompt describes motion — not a static scene. It specifies the same hand, bottle, location, and object, then adds a mandatory transformation sequence: fully rusted object shown, hand enters frame, trigger pressed, spray hits, foam builds rapidly, rust dissolves gradually, clean chrome finish revealed, water droplets drip. This sequence is what makes the videos satisfying to watch and naturally viral.

Note: The system prompt explicitly bans jump cuts and magical transitions. Veo 3 can produce unrealistic glowing effects if the prompt doesn’t constrain it. The “gradual dissolving” instruction is what keeps the physics-based animation believable.

Part 2 — Generating the Image with Kie AI

Step 4 — Generate Image (Kie AI)

This node posts to the Kie AI /jobs/createTask endpoint. It uses the nano-banana-pro model — Kie’s image generation model — with a 9:16 aspect ratio (vertical, for Shorts), 1K resolution, and PNG output. The image prompt from the previous agent goes directly into the input.prompt field. In return, Kie AI gives you a taskId which the polling loop uses to check completion status.

// Generate Image request body
{
  "model": "nano-banana-pro",
  "callBackUrl": "YOUR_CALLBACK_URL",
  "input": {
    "prompt": "{{ $('Image Prompt').item.json.output }}",
    "aspect_ratio": "9:16",
    "resolution": "1K",
    "output_format": "png"
  }
}

// Kie AI response
{
  "data": { "taskId": "img_task_abc123" }
}

Step 5 — Image Polling Loop (Get Image URL + Switch2)

Generating an image takes between 15 and 90 seconds depending on server load. Instead of waiting a fixed amount of time and hoping it’s done, the workflow polls every 30 seconds. The Get Image URL node calls /jobs/recordInfo?taskId=... and the Switch2 node reads $json.data.state. There are four routes: success moves forward and saves the image URL to the sheet, waiting and generating both loop back through a 30-second Wait node, and fail writes “Failed To Generate” to the sheet and stops.

On success, the image URL is extracted from JSON.parse($json.data.resultJson).resultUrls[0] and written to the Image url column. This URL becomes the reference frame for the video generation step.

Tip: You can monitor generation progress in real time by opening your Kie AI dashboard while the workflow runs. The status field cycles through waiting, generating, then success — exactly matching the Switch2 routes.

Part 3 — Generating the Video with Veo 3

Step 6 — Generate Video (Kie AI Veo3 Fast)

With the image URL saved, the workflow posts to Kie AI’s /veo/generate endpoint. The request sends the video prompt, the generated image URL as a reference frame, and specifies veo3_fast as the model with a 9:16 vertical aspect ratio. The generationType is REFERENCE_2_VIDEO — this tells Veo 3 to animate from the reference image rather than generating from text alone. As a result, the video visually matches the generated image, keeping the object and hand consistent.

// Generate Video request body
{
  "prompt": "{{ $('Video Prompt').item.json.output }}",
  "imageUrls": ["{{ $json['Image url'] }}"],
  "model": "veo3_fast",
  "aspect_ratio": "9:16",
  "seeds": 12345,
  "generationType": "REFERENCE_2_VIDEO"
}

Note: The seeds value of 12345 is fixed in the template. Using a consistent seed helps produce repeatable visual styles across different subjects. Change it to a random value if you want more visual variety between videos.

Step 7 — Video Polling Loop (Get Video + Switch)

Video generation takes longer than image generation — typically 2 to 5 minutes. The video polling loop uses the same pattern as the image loop but reads $json.data.successFlag as a number instead of a state string. A value of 1 means success, 0 means still generating, 2 is another in-progress state, and 3 means generation failed. On success, the video URL is extracted from data.response.resultUrls[0] and written to the sheet with Status = Video Generated.

Part 4 — Writing the Caption and Publishing to YouTube

Step 8 — Video Caption (OpenRouter + Claude)

Once the video URL is saved, the workflow calls OpenRouter with the object name as a keyword. Claude 3.7 Sonnet acts as a social media copywriter and returns a YouTube title (maximum 46 characters) followed by five hashtags separated by a blank line. No labels, no emojis, no markdown bold — just clean copy ready for use as a video title and description.

Step 9 — Separate Title From Tags (Code Node)

The Code node splits Claude’s response into two separate fields using a blank line as the delimiter. The first block becomes Title and the second becomes hashtags. Both fields are then written to the Google Sheet in the Video Title and Video Hashtags columns.

const content = $json.choices[0].message.content || "";

// Split on blank line between title and hashtags
const parts = content.split(/\n\s*\n/);

const title    = parts[0] ? parts[0].trim() : "";
const hashtags = parts[1] ? parts[1].trim() : "";

return [{ json: { Title: title, hashtags: hashtags } }];
// Resulting fields written to Google Sheets
{
  "Title": "Rust Remover Works Instantly on Old Wrench",
  "hashtags": "#rustremoval #rustcleaning #satisfyingvideo #restoration #aivideo"
}

Step 10 — Download Video Binary and Upload to YouTube

An HTTP Request node downloads the video binary from the Kie AI CDN URL stored in the sheet. The YouTube Upload node then receives the binary directly, using the saved Video Title as the title and Video Hashtags as the description. The video publishes as public, notifies subscribers, and is tagged with a fixed set of niche-relevant tags covering rust removal, AI video, ASMR, and satisfying content. After a 10-second wait, the Add to Playlist node links the uploaded video to your channel’s Shorts playlist.

Tip: The YouTube category is set to 22 (People and Blogs) in the template. For a rust cleaning channel, category 26 (Howto and Style) may rank better in search. Change the categoryId value in the Upload node parameters.

Step 11 — Update YouTube Status in Google Sheets

Finally, the Add to Playlist response includes contentDetails.videoPublishedAt — the exact UTC timestamp when the video went live. The last Google Sheets node writes this to the Youtube Status column as Video Published — 2026-03-18T14:30:00Z. This gives you a complete audit trail in the sheet: object name, image URL, video URL, title, hashtags, and publish time — all in one row.

The Data Structure — Google Sheets Schema

Create a spreadsheet named Viral with one tab named Sheet1. The column names below are case-sensitive — the workflow uses exact string matching on all update operations.

Column NameTypeExample ValueDescription
objectsTextrusted wrenchThe subject keyword you provide. Drives all AI prompt generation.
Image urlTexthttps://cdn.kie.ai/…/output.pngFilled automatically after image generation succeeds. Set to “Failed To Generate” on failure.
Video UrlTexthttps://cdn.kie.ai/…/video.mp4Filled automatically after video generation succeeds. Set to “Failed To Generate” on failure.
StatusTextpending / Video GeneratedSet to pending by you. Updated to Video Generated by the workflow after the video URL is saved.
Video TitleTextRust Remover Works Instantly on Old WrenchAI-generated YouTube title, max 46 characters.
Video HashtagsText#rustremoval #rustcleaning …Five AI-generated hashtags, used as the YouTube video description.
Youtube StatusTextVideo Published — 2026-03-18T14:30:00ZWritten automatically when the video is added to your YouTube playlist.

Note: Start each new subject by adding a row with the objects field filled in and Status set to pending. Leave all other columns empty — the workflow fills them in automatically as it runs.

Full n8n Viral Shorts Automation Flow — End to End

You add a row: { objects: “rusty bolt”, Status: “pending” } │ ▼ [Manual Trigger] → [Google Sheets: Get pending row] │ ▼ [Image Prompt Agent] → “Ultra-realistic macro photo of extremely rusted bolt…” │ ▼ [Video Prompt Agent] → “Hand enters frame, spray hits bolt, foam builds, rust dissolves…” │ ▼ [Kie AI: Generate Image] → { taskId: “img_abc123” } │ ┌──────▼──────────────────────────────────────────────┐ │ POLL every 30s: GET /jobs/recordInfo?taskId=… │ │ state=waiting/generating → wait 30s → poll again │ │ state=success → Image URL saved to Sheet │ │ state=fail → “Failed To Generate” → STOP │ └──────────────────────────────────────────────────────┘ │ (success) ▼ [Kie AI: Generate Video] → uses image as reference frame │ { taskId: “vid_xyz789” } ┌──────▼──────────────────────────────────────────────┐ │ POLL every 30s: GET /veo/record-info?taskId=… │ │ successFlag=0 or 2 → wait 30s → poll again │ │ successFlag=1 → Video URL saved, Status updated │ │ successFlag=3 → “Failed To Generate” → STOP │ └──────────────────────────────────────────────────────┘ │ (success) ▼ [OpenRouter/Claude: Write title + hashtags] │ [Code: Split title from hashtags] │ [Google Sheets: Save Video Title + Video Hashtags] │ [HTTP Request: Download video binary from CDN] │ [YouTube: Upload video (public, title, description, tags)] │ [Wait 10s] → [YouTube: Add to Playlist] │ [Google Sheets: Update Youtube Status with publish timestamp] │ ▼ Sheet row: { objects: “rusty bolt”, Image url: “https://cdn.kie.ai/…/output.png”, Video Url: “https://cdn.kie.ai/…/video.mp4”, Status: “Video Generated”, Video Title: “Rust Vanishes Off Old Bolt in Seconds”, Video Hashtags: “#rustremoval #aivideo #satisfying …”, Youtube Status: “Video Published — 2026-03-18T14:30:00Z” }

Testing Your n8n Viral Shorts Automation Workflow

  1. Add one row to your Google Sheet with objects = rusty screwdriver and Status = pending. Leave all other columns empty.
  2. In n8n, open the workflow and click Execute workflow. Watch the execution panel — nodes should light green in sequence.
  3. After the Image Prompt and Video Prompt agents run, check the output panel to confirm both prompts contain the mandatory elements: hand, spray bottle, foam, transformation sequence.
  4. After the image polling loop completes, check your Google Sheet. The Image url column should contain a valid Kie AI CDN URL ending in .png.
  5. Wait for the video polling loop to finish (2 to 5 minutes). Confirm Video Url contains an MP4 URL and Status shows Video Generated.
  6. After the caption step, verify Video Title is under 46 characters and Video Hashtags contains exactly five hashtag terms.
  7. After the YouTube upload, open your YouTube Studio and confirm the video appears as a public Short with the correct title, description, and playlist assignment.
  8. Confirm the Youtube Status column shows Video Published with a timestamp.
ProblemLikely CauseFix
Image polling never exits the loop Kie AI task is stuck or the API key has no image generation credits Check your Kie AI dashboard for the task status. Verify your API key has sufficient credits for the nano-banana-pro model.
Image URL saved as undefined The resultJson field is not JSON-parseable in some API responses Add a try-catch around the JSON.parse in the Update row expression, or use $json.data.resultUrls[0] as a fallback path.
Video generation fails immediately (successFlag=3) The image URL passed to Veo 3 is not publicly accessible Open the image URL from the sheet in a browser. If it requires authentication, switch to Kie AI’s public CDN delivery option in your account settings.
YouTube upload returns 403 Forbidden OAuth2 token expired or YouTube Data API not enabled in Google Cloud Console Reconnect the YouTube OAuth2 credential in n8n. In Google Cloud Console, confirm the YouTube Data API v3 is enabled for your project.
Title is longer than 46 characters Claude occasionally exceeds the character limit on certain keywords Add a character truncation step after the Code node: title.substring(0, 46). Alternatively, strengthen the system prompt by adding “The title MUST be 46 characters or fewer — count carefully.”
Google Sheet not updating Column name mismatch — the field names are case-sensitive Verify the headers match exactly: objects, Image url, Video Url, Status, Video Title, Video Hashtags, Youtube Status.

Frequently Asked Questions

Can I use this n8n viral shorts automation for subjects other than rusted objects?

Yes, but the AI prompt agents are currently tuned for the rust-cleaning niche specifically. The system prompts mention spray bottles, foam, corrosion, and chrome finishes. To use a different niche — for example, before-and-after car detailing or dirty sneaker cleaning — rewrite the Image Prompt and Video Prompt system prompts to describe your subject’s transformation sequence. The rest of the workflow is fully niche-agnostic and does not need changes.

How much does it cost to generate one video?

Costs depend on your Kie AI plan and OpenRouter usage. Image generation with nano-banana-pro typically costs a few cents per image. Video generation with Veo3 Fast is more expensive — around $0.10 to $0.30 per video depending on length. Claude 3.7 Sonnet via OpenRouter adds less than $0.01 per caption. For a channel publishing one video per day, total monthly API costs are typically under $15.

Why does the workflow use a manual trigger instead of a schedule?

The manual trigger is the safest starting point. Video generation can take 2 to 5 minutes, and if a scheduled trigger fires while a previous execution is still running, you can end up with duplicate uploads. Once you are confident the workflow runs cleanly end to end, replace the Manual Trigger with a Schedule Trigger set to fire once per day at a time that suits your posting schedule.

What happens if image generation fails?

The Switch2 node routes the fail state to an Update IMG status node, which writes “Failed To Generate” to the Image url column. The workflow then stops — it does not proceed to video generation. The row remains in the sheet with its original Status = pending, so you can manually re-trigger the workflow to retry. For production use, consider changing the status to img_failed and adding a new filter that picks up both pending and img_failed rows.

Can I publish to TikTok or Instagram Reels in addition to YouTube?

The video is generated in 9:16 format, which is correct for all three platforms. After the HTTP Request node downloads the binary, you can add parallel branches: one for YouTube (already built), one for Instagram Reels via the Facebook Graph API, and one for TikTok via their Content Posting API. The binary is the same file — just route it to multiple upload nodes. This is the same pattern used in our Social Media Automation workflow.

How do I change the video model or aspect ratio?

Open the Generate Video node and edit the JSON body directly. Change "model": "veo3_fast" to "veo3" for higher quality at slower speed, or adjust "aspect_ratio" from "9:16" to "16:9" for standard landscape YouTube videos. For landscape videos, also update the Image Prompt system prompt to request a 16:9 aspect ratio — otherwise the reference image and video will have mismatched dimensions.

Get the n8n Viral Shorts Automation Template

Download the ready-to-import workflow JSON and the Google Sheets template with all 7 columns pre-configured — start publishing AI-generated Shorts to YouTube today.

Get the Template

Instant download — works on n8n Cloud and self-hosted

What to Build Next

  • Add a Schedule Trigger — replace the manual trigger with a daily schedule so the workflow publishes one new Short every day without any manual intervention.
  • Expand to multiple niches — duplicate the workflow and change the Image and Video Prompt system prompts for a different transformation niche: car detailing, sneaker cleaning, or power washing.
  • Add Instagram Reels publishing — after the HTTP Request node downloads the binary, add a Facebook Graph API branch to post the same 9:16 video as an Instagram Reel in the same execution.
  • Add a Telegram notification — wire a Telegram node at the end to send yourself a message with the video title and YouTube URL every time a new Short goes live.
  • Browse more automation guides on the EasyWorkflows n8n blog.

Shopify Ai voice store manager n8n 

Managing a Shopify store means checking the dashboard, hunting for order IDs, editing products one by one, and emailing customers manually. Every one of those tasks takes you away from actually growing the business. This n8n Shopify AI agent changes that completely. First, you send a voice note or text message on WhatsApp. Next, the AI understands your command, queries your live store, and takes action — updating orders, managing products, sending customer emails, and logging everything to Google Sheets. As a result, your entire store becomes controllable from your phone, hands-free, in English, Arabic, or French.

Prefer to skip the build? Grab the ready-made template → and be managing your Shopify store by voice in under 20 minutes.

What You’ll Build

  1. You send a WhatsApp text or voice note to your business number — “How many orders came in today?” or “Update the price of the blue hoodie to $49.”
  2. If it’s a voice note, ElevenLabs transcribes the audio to text automatically before passing it to the AI.
  3. The AI agent reads your command, calls the right Shopify tool — get orders, update a product, create a listing, delete a variant — and executes it against your live store.
  4. Order data is written to a Google Sheet for tracking, and customer emails are sent via Gmail when you ask.
  5. The AI replies back to WhatsApp: text if you typed, a voice note in the same Charlie voice if you spoke.
  6. Every conversation is remembered per WhatsApp contact, so context carries forward across messages.

How This n8n Shopify AI Agent Works — The Big Picture

The workflow has two entry paths that merge at the AI agent, and two exit paths that split again based on whether the original message was text or audio. In between, the AI has six Shopify tools it can call autonomously, plus Google Sheets and Gmail. Here is the full picture:

┌──────────────────────────────────────────────────────────────────────────────┐
│  N8N SHOPIFY AI AGENT — WHATSAPP VOICE STORE MANAGER                        │
│                                                                              │
│  [WhatsApp Trigger]                                                          │
│          │                                                                   │
│          ▼                                                                   │
│  [Switch: text or audio?]                                                    │
│     │ text                   │ audio                                         │
│     ▼                        ▼                                               │
│  (straight to          [Get Media URL]                                       │
│   AI Agent)            [Download Audio Binary]                               │
│                        [ElevenLabs: Speech-to-Text]                         │
│                              │                                               │
│                    ──────────┘                                               │
│                    ▼                                                         │
│           [AI Agent — Store Manager]                                         │
│            │  Tools available:                                               │
│            ├─ [Shopify: Get Orders]                                          │
│            ├─ [Shopify: Get Products]                                        │
│            ├─ [Shopify: Update Order]                                        │
│            ├─ [Shopify: Create Product]                                      │
│            ├─ [Shopify: Update Product]                                      │
│            ├─ [Shopify: Delete Product]                                      │
│            ├─ [Google Sheets: database (append/update)]                      │
│            └─ [Gmail: Send Email]                                            │
│            │  Memory: Simple Memory (per WhatsApp contact)                  │
│            │  Model:  OpenRouter Chat Model                                  │
│                    │                                                         │
│                    ▼                                                         │
│           [Switch1: was original text or audio?]                             │
│             │ text                    │ audio                                │
│             ▼                         ▼                                      │
│    [WhatsApp: Send text]    [ElevenLabs: Text-to-Speech]                    │
│                             [Code: Set MIME → audio/mpeg]                   │
│                             [WhatsApp: Send voice note]                     │
└──────────────────────────────────────────────────────────────────────────────┘

What You’ll Need

  • n8n — self-hosted or n8n Cloud (v1.30+). See the n8n hosting documentation for setup options.
  • WhatsApp Business API — a verified Meta business phone number with a permanent access token. See the WhatsApp Cloud API getting-started guide.
  • Shopify store — with a private app or OAuth app that has read/write access to Orders and Products.
  • ElevenLabs account — free tier works for testing; choose any voice from your library.
  • OpenRouter account — to power the AI agent; Claude, GPT-4o, or Llama 3 all work.
  • Google Sheets — one spreadsheet with an “orders” tab containing the 14-column schema shown below.
  • Gmail account — connected via OAuth2 in n8n for sending customer emails.

Estimated build time: 60–90 minutes from scratch, or under 20 minutes with the ready-made template.

Part 1 — Receiving the WhatsApp Message

1 WhatsApp Trigger

This node opens a webhook endpoint that Meta’s WhatsApp Cloud API calls every time a message arrives on your business number. It listens for the messages event type, which covers both text messages and media (audio, images, documents). Every incoming message delivers a payload with two fields the rest of the workflow relies on: messages[0].type (either text or audio) and contacts[0].wa_id (the sender’s phone number, used as the session key for memory).

// Incoming WhatsApp payload — text message example
{
  "messages": [
    {
      "type": "text",
      "text": { "body": "How many orders are pending today?" }
    }
  ],
  "contacts": [
    { "wa_id": "15551234567", "profile": { "name": "Sarah Thompson" } }
  ]
}
📌

Note: Your WhatsApp webhook must be registered in the Meta Developer Console pointing to your n8n webhook URL. The verification token is set in the WhatsApp Trigger node credentials. Make sure your n8n instance is publicly reachable — it cannot run on localhost.

2 Switch — Text or Audio?

First, the Switch node reads $json.messages[0].type. If it equals text, the message goes directly to the AI Agent. If it equals audio, the message takes a detour through three nodes to transcribe the voice note before the AI sees it. This routing is what makes the workflow truly voice-native — the AI always receives clean text, regardless of how the user communicated.

// Switch routing logic
{
  "route_text":  "messages[0].type === 'text'",
  "route_audio": "messages[0].type === 'audio'"
}

Part 2 — Transcribing Voice Messages

3 Download Media (WhatsApp)

When the message is audio, this node calls the WhatsApp media endpoint to get the audio file’s download URL. It passes $json.messages[0].audio.id — the media ID from the trigger payload — and receives back a temporary URL that expires after a few minutes.

4 Download Audio (HTTP Request)

Next, this HTTP Request node fetches the actual audio binary from the URL returned by the previous step. It uses the WhatsApp API credentials for authentication, since Meta’s media URLs require a valid access token in the request headers. The output is a binary file that ElevenLabs can process.

5 Transcribe Audio (ElevenLabs)

ElevenLabs Speech-to-Text converts the audio binary into plain text with high accuracy, including for Arabic and French — matching the multilingual capability of the AI agent. The transcribed text arrives as $json.text, which the AI Agent reads via its Audio input: {{ $json.text }} prompt field.

💡

Tip: ElevenLabs handles background noise, accents, and mixed-language voice notes well. For store managers recording quick commands while walking around a warehouse, this reliability is critical. If you want to reduce API costs, you can swap ElevenLabs for OpenAI’s Whisper node, which is cheaper for high-volume transcription.

Part 3 — The AI Store Manager Agent

6 AI Agent — Store Manager

This is the brain of the entire workflow. The AI Agent node receives either the text body or the transcribed audio, then decides which tools to call and in what order to fulfill the command. Its system prompt defines its role as a Shopify store manager, its available tools, its language capabilities, and one important rule: always call Get orders before updating an order, to retrieve the order ID first.

The agent prompt sets the behavior clearly. For example, the current system prompt instructs:

role: You are a smart AI voice Store Manager for my Shopify Store.
tasks:
- Always use 'Get orders' to get order/sales details
- Before you update orders, always get the order ID first from 'Get orders'
tools: shopify tool, Google Sheets 'database', Gmail
languages: English, Arabic (Modern Standard Arabic), French
💡

Tip: The system prompt mentions “Pet_shop” as the Gmail sender name — update this to your actual store name in both the AI Agent system prompt and the Gmail Tool node’s senderName field before going live.

7 OpenRouter Chat Model

The AI Agent is powered by OpenRouter, which gives you access to 100+ language models through a single API key. The default model is not hardcoded — you choose it in the OpenRouter Chat Model node’s dropdown. For store management commands (structured data retrieval, product updates), Claude 3.5 Sonnet or GPT-4o Mini deliver excellent results at low cost. Switch models any time without touching the rest of the workflow.

8 Simple Memory

The memory node gives the agent a 20-message conversation window, keyed to each contact’s WhatsApp phone number (wa_id). This means when a user follows up with “Actually, add a note to that order saying urgent delivery,” the agent remembers which order they were discussing without being told again. Each WhatsApp contact gets a fully isolated conversation context — 50 customers messaging simultaneously creates 50 separate memory streams.

Part 4 — Shopify Tools the Agent Can Use

The AI agent has six Shopify tools available. It calls them autonomously — you never have to specify which tool to use in your WhatsApp message. Just describe what you want in plain language, and the agent decides.

ToolWhat it doesExample command that triggers it
Get Orders Fetches all orders from Shopify. The agent controls returnAll and limit via $fromAI() based on your request. “Show me today’s orders” / “How many pending orders do we have?”
Get Products Fetches all products from the catalog. Returns titles, prices, variants, and inventory levels. “List all products under $30” / “Do we still have the red sneakers in stock?”
Update an Order Updates an order by ID. First calls Get Orders to find the correct ID, then applies changes like notes or tags. “Add a note to order #1023 saying the customer requested gift wrapping.”
Create a Product Creates a new product with a title and optional additional fields (description, price, images). “Create a new product called Summer Linen Tote Bag at $24.99.”
Update a Product Updates a product’s title and HTML body description by product ID. First calls Get Products to find the ID. “Update the Blue Hoodie description to add washing instructions.”
Delete a Product Permanently deletes a product from Shopify by product ID. “Remove the discontinued Winter Scarf from the catalog.”
📌

Important: The Delete a product tool is permanent. There is no confirmation step — if the AI identifies the product and you asked it to delete, it will. Add a safety confirmation step (an IF node or a WhatsApp confirmation reply) if you want to prevent accidental deletions in production.

Part 5 — Database and Email Tools

9 Google Sheets — Database Tool

Every time the agent retrieves or acts on an order, it can write the data to your Google Sheet using the appendOrUpdate operation. The Order ID column is the matching key — so re-running a command on the same order updates the existing row rather than duplicating it. All 14 fields are populated via $fromAI() expressions, meaning the agent extracts each value from the Shopify response and maps it automatically.

10 Gmail — Send Email Tool

When you ask the agent to email a customer, it calls this tool, filling the To, Subject, and Message fields via $fromAI(). The sender name is set to your store name. For example, you can say: “Email james.carter@gmail.com and tell him his order shipped today” — and the agent writes and sends the email entirely on its own.

Part 6 — Sending the Reply

11 Switch1 — Reply in Text or Voice?

After the AI agent finishes, a second Switch node checks the original message type again. If you sent text, you get a text reply. If you sent a voice note, the agent converts its response to speech and sends a voice note back. The reply always matches the input format — a voice conversation stays a voice conversation.

12 Convert Text to Speech (ElevenLabs)

For audio replies, this node sends the AI agent’s text output to ElevenLabs using the “Charlie — Deep, Confident, Energetic” voice. The settings are configured for natural, professional delivery: stability at 1.0, similarity boost at 1.0, and speed at 0.82 (slightly slower than default, which works better for information-dense store management replies). The output format is MP3 at 22050 Hz.

13 Convert to MPEG (Code Node)

WhatsApp’s API is strict about audio MIME types. This Code node sets mimeType to audio/mpeg and renames the file to voice.mp3 — without this step, WhatsApp rejects the audio upload and the voice reply fails silently.

for (const item of $input.all()) {
  if (item.binary && item.binary.data) {
    item.binary.data.mimeType = 'audio/mpeg'
    item.binary.data.fileName = 'voice.mp3'
  }
}
return $input.all();

14 Send Message / Send Message1 (WhatsApp)

Two WhatsApp send nodes handle the two reply paths. Send message1 (text path) sends the AI output as a plain text body. Send message (audio path) sends the MPEG binary as an audio message. Both always reply to the original sender using $('WhatsApp Trigger').item.json.contacts[0].wa_id.

The Data Structure — Google Sheets Order Database

Create a Google Sheet with one tab named orders. The column names below are case-sensitive — the agent uses them as keys when writing rows via $fromAI().

Column NameTypeExample ValueDescription
Order IDText5678901234Shopify order ID — used as the matching key to prevent duplicate rows
Order NameText#1023Human-readable order name shown in the Shopify dashboard
Order DateTextMarch 18, 2026Date the order was placed
Customer NameTextJames CarterFull name from the Shopify order
Customer EmailTextjames.carter@gmail.comUsed when sending confirmation emails via Gmail
Customer PhoneText(555) 867-5309Contact number from the order
Product TitleTextBlue Hoodie — Size MProduct name and variant from the order line item
QuantityText2Number of units ordered
Product PriceText$49.00Unit price at time of order
Total Order AmountText$98.00Full order total including all line items
CurrencyTextUSDCurrency code from the Shopify order
Payment StatusTextpaidShopify financial status: paid, pending, refunded
SourceTextonline_storeOrder source channel from Shopify
Agent NoteTextCustomer requested express shippingAI-generated note about the order based on conversation context
📌

Setup step: Create the sheet with these exact headers before activating the workflow. The Order ID column is the matching key — a second write with the same ID updates the existing row instead of creating a duplicate. Name the tab exactly orders (lowercase) to match the workflow configuration.

Full System Flow — n8n Shopify AI Agent End to End

You send a WhatsApp message: "Update the Blue Hoodie price to $44"
          │
          ▼
[WhatsApp Trigger] → { messages[0].type: "text", text.body: "Update the Blue Hoodie price to $44" }
          │
          ▼
[Switch: type = "text"] → routes to AI Agent directly
          │
          ▼
[AI Agent — Store Manager]
  → calls [Get Products] → finds Blue Hoodie, product_id: 7890123456
  → calls [Update a Product] → sets title + new price on Shopify
  → calls [Google Sheets database] → logs order/product change
  → generates reply: "Done! Blue Hoodie updated to $44.00 in your store."
          │
          ▼
[Switch1: original type = "text"]
          │
          ▼
[WhatsApp: Send text reply] → "Done! Blue Hoodie updated to $44.00 in your store."

────────────────────────────────────────────────────────────

You send a WhatsApp voice note: "Send an email to James about his order"
          │
          ▼
[WhatsApp Trigger] → { messages[0].type: "audio", audio.id: "media_id_xyz" }
          │
          ▼
[Switch: type = "audio"] → routes to audio transcription path
          │
[Download Media URL] → { url: "https://lookaside.fbsbx.com/..." }
[Download Audio Binary] → binary MP3 file
[ElevenLabs: Speech-to-Text] → { text: "Send an email to James about his order" }
          │
          ▼
[AI Agent — Store Manager]
  → calls [Get Orders] → finds James Carter, order #1023, james.carter@gmail.com
  → calls [Gmail: Send Email] → sends order update email to james.carter@gmail.com
  → generates reply: "Email sent to James Carter at james.carter@gmail.com for order #1023."
          │
          ▼
[Switch1: original type = "audio"]
          │
[ElevenLabs: Text-to-Speech] → MP3 audio of reply in Charlie voice
[Code: Set mimeType = audio/mpeg]
[WhatsApp: Send voice note] → 🔊 Voice reply delivered to sender

Testing Your n8n Shopify AI Agent

  1. In n8n, activate the workflow and copy the WhatsApp webhook URL. Register it in the Meta Developer Console under your app’s webhook settings.
  2. Send a text message to your WhatsApp business number: “List all products.” Confirm the AI responds with your actual Shopify catalog.
  3. Send a voice note saying: “How many orders do we have this week?” Confirm the audio is transcribed, the AI calls Get Orders, and you receive a voice reply with the count.
  4. Send: “Create a test product called Test Widget at $9.99.” Check your Shopify Products dashboard to confirm it appeared.
  5. Send: “Delete the Test Widget product.” Confirm it’s removed from Shopify. Then send the same command again — the AI should respond that the product no longer exists, demonstrating it uses Get Products before acting.
  6. Send: “Email emily.rodriguez@outlook.com and tell her order #1001 has shipped.” Check your Gmail Sent folder to confirm the email was sent with the correct content.
  7. Open your Google Sheet and confirm order rows are being written or updated correctly.
ProblemLikely CauseFix
Webhook not receiving messages n8n URL not registered in Meta Developer Console, or instance not publicly accessible Verify the webhook URL and token in Meta Developer Console → WhatsApp → Configuration. Use ngrok for local testing.
Voice reply fails — audio not delivered Missing MIME type fix or wrong phone number ID Confirm the “Convert to mpeg” Code node runs before the send node. Replace YOUR_WHATSAPP_PHONE_NUMBER_ID with your actual Phone Number ID from the Meta console.
AI says “I can’t find that product” but it exists Agent is not calling Get Products before Update Product Add an explicit instruction to the system prompt: “Always call Get Products before updating or deleting any product.”
Google Sheet not updating Column names don’t match exactly (case-sensitive) Compare sheet headers character-by-character against the schema table above. Make sure the tab is named orders.
Gmail not sending OAuth2 token expired or incorrect sender name Reconnect the Gmail OAuth2 credential in n8n. Update senderName in the Gmail Tool node from “Pet_shop” to your store name.
AI responds in the wrong language Language detection relies on user input — mixed messages can confuse it Update the system prompt to specify a default language: “If the language is unclear, respond in English.”

Frequently Asked Questions

Does this n8n Shopify AI agent work with Shopify Basic, Grow, or Advanced plans?

Yes. The workflow uses the Shopify REST API via n8n’s native Shopify nodes, which are available on all paid Shopify plans. You need to create a custom app in your Shopify admin under Settings → Apps → Develop apps and grant it read/write access to Orders and Products. The API credentials generated there connect directly to the Shopify nodes in the workflow.

Can multiple team members use the same WhatsApp number to control the store?

Yes. The Simple Memory node isolates each conversation by WhatsApp phone number, so two managers messaging the same business number get completely separate conversation contexts. There is no cross-contamination — one manager asking about orders does not affect the other’s session. For team use, consider adding an authorization check at the start of the workflow to restrict commands to known wa_id numbers.

Which AI model should I use with OpenRouter for best results?

For store management tasks — structured queries, product lookups, order updates — Claude 3.5 Sonnet or GPT-4o Mini both perform excellently. Claude handles Arabic and French more naturally, making it the better choice if your team works in multiple languages. For pure speed and lowest cost, GPT-4o Mini is the most efficient. Avoid smaller models (7B parameters or less) as they tend to mis-call tools on complex multi-step commands.

Can I add more Shopify actions beyond what’s included?

Absolutely. n8n’s Shopify Tool node supports many additional operations: creating customers, managing fulfillments, updating inventory levels, and more. To add a new capability, duplicate one of the existing Shopify Tool nodes, change the operation, connect it to the AI Agent’s tools input, and add a brief description of what the tool does in the node’s description field — the AI will use it automatically when appropriate.

What happens if the AI tries to delete the wrong product?

By design, the agent calls Get Products first to look up the product ID before deleting. However, there is no confirmation step in the base workflow. For production use, it is strongly recommended to add a safety layer: before the Delete node fires, send a WhatsApp message asking “Are you sure you want to delete [product name]? Reply YES to confirm.” Then use a Wait node and a conditional check on the reply before proceeding.

Can I connect this to a customer-facing WhatsApp number instead of an internal one?

The workflow as built is designed for internal store manager use. Connecting it to a customer-facing number would require a completely different system prompt and much stricter guardrails — the current prompt gives full write access to products and orders, which customers must never have. For a customer-facing chatbot, see our separate AI WooCommerce Chatbot guide which is designed specifically for that use case.

🚀 Get the n8n Shopify AI Agent Template

Download the ready-to-import workflow JSON, the Google Sheets order database template with all 14 columns pre-configured, and a step-by-step credential setup guide — so you can manage your Shopify store by WhatsApp voice in under 20 minutes.

Get the Template →

Instant download · Works on n8n Cloud and self-hosted

What’s Next?

  • Add a daily sales report — wire a Schedule Trigger that fires every morning and sends you a voice note summarizing the previous day’s orders, revenue, and top-selling products.
  • Add inventory alerts — extend the Get Products tool call to check stock levels and automatically send a WhatsApp alert when any product drops below a minimum quantity you define.
  • Connect Telegram as a second channel — duplicate the WhatsApp input/output nodes and replace them with Telegram nodes so the same AI agent is accessible from both apps with shared memory.
  • Add a safety confirmation step — before any destructive action (delete product, cancel order), add a WhatsApp reply asking for confirmation, then a Wait node and an IF check on the response.
  • Browse all our automation guides on the EasyWorkflows n8n blog →

How to Automate Social Media Posting Across Instagram, Facebook & YouTube with n8n

How to Automate Social Media Posting Across Instagram, Facebook & YouTube with n8n

One workflow, one Google Drive folder, four platforms. Drop a video, walk away — n8n handles the AI caption, the upload, the publish, and the status tracking automatically.

If you’re posting the same video to Instagram Reels, Facebook Reels, YouTube, and TikTok, you already know the drill: download, re-upload, write a caption, find the right tags, publish, check the status, repeat — four times, for every single video. It’s not a content problem. It’s a logistics problem. And logistics problems are exactly what n8n was built to solve.

This workflow watches a Google Drive folder, picks up the next unprocessed video, uses an AI model via OpenRouter to generate a platform-optimized caption with hashtags, uploads the video to Cloudinary as a CDN host, then simultaneously publishes it as a Reel on Instagram, a Reel on Facebook, and a video on YouTube — while staging the data for TikTok in a separate sheet. Every step is tracked in a Google Sheet so your team always knows what’s been published and what’s still pending. When everything is done, the original file is moved to an archive folder so it doesn’t get picked up again.

Prefer to skip the setup? Grab the ready-made template → and be publishing cross-platform in under 20 minutes.

What You’ll Build

  1. A daily schedule trigger (fires at 6 PM) scans your Google Drive folder for the next video waiting to be published.
  2. A Code node strips the file extension and normalizes the filename into a clean public ID (spaces become underscores for Cloudinary).
  3. The video is uploaded to Cloudinary, which provides a stable public CDN URL that all four platforms can download from.
  4. An AI call to OpenRouter (Claude 3.7 Sonnet) reads the filename as a keyword and writes a Facebook-optimized caption with five hashtags — no manual copywriting needed.
  5. The Cloudinary URL and AI caption are written back to your Google Sheet tracking row.
  6. The video is published as a Reel on Facebook (via the Facebook Graph API) and simultaneously as a Reel on Instagram — with 30-second waits built in between API calls to respect rate limits.
  7. The same video is uploaded to YouTube with the AI caption as the description, then added to a playlist.
  8. A separate Google Sheets tab gets a row appended for your TikTok queue (ready for the next manual step or a future TikTok automation).
  9. The main tracking sheet updates the row status to “Video Shared”, and the original Drive file is moved to your archive folder.

How It Works — The Big Picture

┌──────────────────────────────────────────────────────────────────────────────┐
│  SOCIAL MEDIA AUTOMATION (n8n)                                               │
│                                                                              │
│  [Schedule Trigger 6PM] ──► [Google Drive: Search Folder]                   │
│                                        │                                     │
│                                        ▼                                     │
│                              [Code: Clean Filename]                          │
│                                        │                                     │
│                                        ▼                                     │
│                              [Cloudinary: Upload Video]                      │
│                                        │                                     │
│                                        ▼                                     │
│                          [Sheets: Get Pending Row]                           │
│                                        │                                     │
│                                        ▼                                     │
│                         [OpenRouter AI: Generate Caption]                    │
│                                        │                                     │
│                                        ▼                                     │
│                         [Sheets: Write URL + Caption]                        │
│                                        │                                     │
│               ┌────────────────────────┤                                     │
│               │                        │                                     │
│               ▼                        ▼                                     │
│  ── FACEBOOK REELS ──       ── INSTAGRAM REELS ──                           │
│  [Init Upload Session]       [Post Container]                               │
│  [Upload Hosted File]        [Wait 30s]                                     │
│  [Publish Reel]              [Publish to Instagram]                         │
│  [Get Upload Status]         [Wait 30s]                                     │
│  [Wait 30s]                  [HTTP: Fetch Video]                            │
│               │                        │                                     │
│               └────────────────────────┘                                     │
│                                        │                                     │
│                                        ▼                                     │
│                         ── YOUTUBE ──                                        │
│                         [Upload Video]                                       │
│                         [Wait 10s]                                           │
│                         [Add to Playlist]                                    │
│                         [Wait 10s]                                           │
│                         [Sheets: Append TikTok Row]                         │
│                                        │                                     │
│                                        ▼                                     │
│                         [Sheets: Update Status → "Video Shared"]            │
│                         [Google Drive: Move to Archive Folder]              │
└──────────────────────────────────────────────────────────────────────────────┘

What You’ll Need

  • n8n — self-hosted or n8n Cloud (v1.30+)
  • Google Drive — one folder for new videos, one for archived videos
  • Cloudinary account — free tier is sufficient; the Social_Media folder will be created automatically
  • OpenRouter account — free tier works; Claude 3.7 Sonnet is configured by default (swap to any model you prefer)
  • Meta Developer App — with a Facebook Page token and an Instagram Business account linked to that page
  • YouTube Data API v3 — OAuth2 credentials connected in n8n; a playlist ID to post into
  • Google Sheets — one spreadsheet with two tabs: one for Instagram/Facebook/YouTube tracking, one for TikTok queue

Estimated build time: 90–120 minutes from scratch. Under 20 minutes with the template.

Part 1 — Picking Up the Video

1 Schedule Trigger

The workflow fires once a day at 6 PM. You can change this to any hour — just edit the Trigger At Hour field in the Schedule Trigger node. If you want to post multiple times a day, duplicate the trigger or switch to an interval-based schedule.

// Schedule Trigger output (no data — just fires the workflow)
{}
💡

Tip: To publish a different video every day, just make sure your Drive folder always has the next video waiting before 6 PM. The workflow picks up the first file it finds, processes it, and archives it — so the order files appear in Drive determines your posting schedule.

2 Search Files and Folders (Google Drive)

This node lists files inside your designated Google Drive folder, returning the first result it finds (limit: 1). It fetches all fields, including webContentLink — a direct download URL that Cloudinary will use to pull the video.

// Google Drive file output
{
  "id": "1aBcDeFgHiJkLmNoPqRsTuV",
  "name": "Summer Sale Promo.mp4",
  "webContentLink": "https://drive.google.com/uc?id=1aBcDeFgHiJkLmNoPqRsTuV&export=download",
  "mimeType": "video/mp4",
  "size": "48234567"
}
📌

Important: Set the folder ID to your “pending videos” folder in the Google Drive node. Leave the archive folder ID empty for now — you’ll fill it into the Move file1 node at the end of the workflow.

3 Remove Space & Extensions (Code Node)

Platform APIs and CDNs don’t love filenames with spaces or extensions. This Code node strips the .mp4 (or any extension) from the filename and produces two variants: one with underscores (for Cloudinary’s public_id) and one with the original spaces preserved (for YouTube’s video title, which looks better with natural spacing).

const baseName = $json["name"]
  .replace(/\s*\.[^/.]+$/, "")  // remove file extension
  .trim();

const public_id_underscores = baseName.replace(/\s+/g, "_"); // spaces → underscores
const public_id_no_underscores = baseName;                    // natural spacing

return [{ json: { public_id_underscores, public_id_no_underscores } }];
// Output
{
  "public_id_underscores": "Summer_Sale_Promo",
  "public_id_no_underscores": "Summer Sale Promo"
}

Part 2 — Uploading to Cloudinary

4 Upload an Asset from URL (Cloudinary)

Rather than downloading the video to n8n’s memory and re-uploading it, this node passes Cloudinary the Google Drive download link directly. Cloudinary fetches it server-to-server, transcodes it if needed, and stores it in your Social_Media folder with the underscore-normalized name as the public ID. In return, Cloudinary hands you a secure_url — the stable CDN link that all four platforms will pull from.

// Cloudinary upload output (key fields)
{
  "public_id": "Social_Media/Summer_Sale_Promo",
  "secure_url": "https://res.cloudinary.com/your-cloud/video/upload/Social_Media/Summer_Sale_Promo.mp4",
  "resource_type": "video",
  "format": "mp4",
  "duration": 28.4,
  "bytes": 48234567
}
💡

Tip: Cloudinary’s free tier gives you 25 GB of storage and 25 GB of monthly bandwidth — more than enough to test with. Videos are stored permanently so you can reuse the same CDN URL if you ever need to repost.

Part 3 — AI Caption Generation

5 Get Row(s) in Sheet (Google Sheets)

This node looks up the first row in your tracking sheet where the Status column is set to pending. It returns all columns for that row, including its row_number — which is used later to update the same row in place rather than creating a duplicate.

// Google Sheets row output
{
  "row_number": 4,
  "video_url": "",
  "Video Caption": "",
  "Status": "pending"
}

6 Video Caption (OpenRouter AI)

This HTTP Request node calls the OpenRouter API, sending the cleaned filename as the keyword. The system prompt tells Claude 3.7 Sonnet to act as a Facebook copywriter and return a Reel title (max 46 characters) followed by five relevant hashtags — no labels, no emojis, no markdown bold formatting. Clean, ready-to-paste copy every time.

// Request body (simplified)
{
  "model": "anthropic/claude-3.7-sonnet",
  "messages": [
    {
      "role": "system",
      "content": "You are a facebook copywriter expert. Follow formatting rules exactly."
    },
    {
      "role": "user",
      "content": "based on this keyword Summer Sale Promo Write an optimized facebook Reel title (max 46 characters), use 5 related hashtags, Do NOT include labels like (Video Reel Title, Hashtags) no emojis, don't use ** in title."
    }
  ]
}
// OpenRouter response
{
  "choices": [
    {
      "message": {
        "content": "Summer Sale — Shop the Best Deals Now\n#SummerSale #ShopNow #SaleAlert #BestDeals #LimitedTime"
      }
    }
  ]
}
💡

Tip: You can swap Claude 3.7 Sonnet for any model on OpenRouter — GPT-4o Mini, Mistral, or Llama 3 all work. For pure caption writing, GPT-4o Mini costs a fraction of a cent per request and produces great results.

7 Update Caption & Video URL (Google Sheets)

Once the AI returns the caption and Cloudinary returns the CDN URL, this node writes both values back to the pending row — matching by row_number. From this point on, every downstream node references these two fields using $('Update caption & vid url').item.json.video_url and $('Update caption & vid url').item.json['Video Caption'].

// Updated row in Google Sheets
{
  "row_number": 4,
  "video_url": "https://res.cloudinary.com/your-cloud/video/upload/Social_Media/Summer_Sale_Promo.mp4",
  "Video Caption": "Summer Sale — Shop the Best Deals Now\n#SummerSale #ShopNow #SaleAlert #BestDeals #LimitedTime",
  "Status": "pending"
}

Part 4 — Publishing to Facebook Reels

Facebook’s Reels API uses a three-step upload protocol: initialize a session, upload the file, then publish. n8n handles all three calls in sequence with a 30-second wait before the publish check — giving Facebook’s servers time to process the video before you query the status.

8 Initialize an Upload Session (Facebook Graph API)

Sends a POST to your Facebook Page’s video_reels edge with upload_phase=start and the Cloudinary video URL. Facebook returns a video_id and an upload_url that the next node uses.

// Facebook API response
{
  "video_id": "740128398210437",
  "upload_url": "https://rupload.facebook.com/video-upload/v23.0/740128398210437"
}

9 Upload a Hosted File (HTTP Request)

Posts to the upload_url from the previous step, passing the Cloudinary URL in a custom file_url header. Facebook fetches the video directly from Cloudinary — no binary upload, no memory usage in n8n.

10 Publish The Reel (Facebook Graph API)

Sends the finish signal: upload_phase=finish, video_state=PUBLISHED, the AI-generated description, and the video_id. This is the moment the Reel goes live on your Facebook Page.

11 Get the Upload Status + Wait 30s

Queries the Facebook Graph API to confirm the video’s status field. The 30-second Wait node before Instagram publishing gives Facebook time to fully process the reel and updates internal state before the workflow moves on.

Part 5 — Publishing to Instagram Reels

12 Post Container (Facebook Graph API — Instagram)

Instagram’s publishing API (also part of the Facebook Graph API) requires a two-step process. First, create a media container by posting the video URL, caption, and media_type=REELS to your Instagram Business account’s media edge. This returns a container id.

13 Wait 30s → Publish to Instagram

The 30-second wait is mandatory — Instagram needs time to process the video before you can publish the container. After the wait, a second API call to the media_publish edge with the creation_id makes the Reel visible on your Instagram profile.

📌

Note: You need a Facebook Page and an Instagram Business account connected to it under the same Meta Developer App. Personal Instagram accounts cannot use the Reels API.

Part 6 — Publishing to YouTube

14 HTTP Request — Fetch Video Binary

This node downloads the video binary from the Cloudinary URL. YouTube’s n8n node expects a binary input (unlike the Facebook API which accepts a URL), so this step bridges the gap — the response body becomes the binary data that the YouTube Upload node reads.

15 Upload a Video (YouTube)

Uploads the binary to YouTube. The title uses the un-modified filename (public_id_no_underscores — natural spaces), the description gets the AI-generated caption, and the video is published as public with notifySubscribers: true. Category 22 is “People & Blogs” — change this to match your niche.

// YouTube upload output (key fields)
{
  "uploadId": "abc123XYZ_youTubeVideoId",
  "status": { "privacyStatus": "public", "uploadStatus": "uploaded" },
  "snippet": { "title": "Summer Sale Promo", "categoryId": "22" }
}

16 Add to Playlist (YouTube)

After a 10-second wait (gives YouTube time to finish processing the upload), this node adds the video to your designated playlist using the uploadId from the previous step. Set your playlist ID in the node parameters.

Part 7 — Tracking and Cleanup

17 Append Row to TikTok Sheet (Google Sheets)

After a second 10-second wait, this node appends a new row to a separate “TikTok” tab in your spreadsheet with the video URL and caption — ready for you to post manually or wire up to a future TikTok API automation.

18 Update Row Status (Google Sheets)

Updates the original tracking row from pending to Video Shared, matched by row_number. This prevents the same video from being picked up again on the next trigger run.

19 Move File to Archive (Google Drive)

Moves the original video file from your “pending” folder to your “archive” folder. The file ID comes from the very first node (Search files and folders). Set your archive folder ID in this node’s parameters.

💡

Tip: If you’d rather delete the file from Drive than archive it, swap this node for a Google Drive Delete node. Archiving is recommended so you have a record of what was posted and can repost if needed.

The Data Structure

Your Google Sheet needs two tabs with these exact column names. The workflow uses string matching on column headers, so capitalization and spacing matter.

Tab 1: instagram / Facebook / Youtube

Column NameTypeExample ValueDescription
video_urlTexthttps://res.cloudinary.com/…/Summer_Sale_Promo.mp4Filled automatically by the workflow after Cloudinary upload
Video CaptionTextSummer Sale — Shop the Best Deals Now
#SummerSale #ShopNow…
AI-generated caption; filled automatically by the workflow
StatusTextpendingVideo SharedSet to “pending” manually when you add a video; updated to “Video Shared” after publishing

Tab 2: Tiktok

Column NameTypeExample ValueDescription
video_urlTexthttps://res.cloudinary.com/…/Summer_Sale_Promo.mp4Same Cloudinary URL — ready for TikTok posting
Video CaptionTextSummer Sale — Shop the Best Deals Now
#SummerSale…
Same AI caption — TikTok hashtag format works identically
📌

Setup step: Before activating the workflow, add one row to Tab 1 with Status = pending and leave video_url and Video Caption blank — the workflow fills those in automatically. Make sure the video file is already in your Google Drive folder.

Full System Flow

New video dropped into Google Drive "Pending" folder
          │
          ▼
[Schedule Trigger: 6PM daily]
          │
          ▼
[Google Drive: Search Folder] → { name: "Summer Sale Promo.mp4", webContentLink: "..." }
          │
          ▼
[Code: Clean Filename] → { public_id_underscores: "Summer_Sale_Promo",
                            public_id_no_underscores: "Summer Sale Promo" }
          │
          ▼
[Cloudinary: Upload Video] → { secure_url: "https://res.cloudinary.com/.../Summer_Sale_Promo.mp4" }
          │
          ▼
[Sheets: Get Pending Row] → { row_number: 4, Status: "pending" }
          │
          ▼
[OpenRouter AI: Generate Caption] → "Summer Sale — Shop the Best Deals Now\n#SummerSale..."
          │
          ▼
[Sheets: Write URL + Caption to Row 4]
          │
    ┌─────┴──────────────────────────────────┐
    ▼                                        ▼
── FACEBOOK ──                       ── INSTAGRAM ──
[Init Upload Session]                [Post Container] → { id: "17867..." }
[Upload Hosted File]                 [Wait 30s]
[Publish Reel]                       [Publish to Instagram]
[Get Upload Status]                  [Wait 30s]
[Wait 30s]                           [Fetch Video Binary (HTTP)]
    │                                        │
    └──────────────────┬─────────────────────┘
                       ▼
                 ── YOUTUBE ──
                 [Upload Video] → { uploadId: "abc123..." }
                 [Wait 10s]
                 [Add to Playlist]
                 [Wait 10s]
                 [Sheets: Append TikTok Row]
                       │
                       ▼
                 [Sheets: Update Status → "Video Shared"]
                 [Google Drive: Move to Archive Folder]
                       │
                       ▼
            ✅ Video live on Facebook, Instagram & YouTube
               TikTok row ready in queue sheet

Testing Your Workflow

  1. Add a short test video (under 60 seconds) to your Google Drive “pending” folder.
  2. Add a row to Tab 1 of your Google Sheet with Status = pending, leave other fields blank.
  3. In n8n, click Test workflow. Watch the execution — look for green checks on each node.
  4. Confirm the Code node output shows both public_id_underscores and public_id_no_underscores.
  5. Check your Cloudinary account to verify the video was uploaded to the Social_Media folder.
  6. Confirm the Google Sheet row now has a video_url and Video Caption filled in.
  7. Check your Facebook Page and Instagram profile for the new Reel (allow 2–3 minutes for processing).
  8. Check your YouTube channel for the new video and confirm it was added to the correct playlist.
  9. Verify the TikTok sheet has a new row appended.
  10. Confirm the original Google Drive file has been moved to the archive folder.
ProblemLikely CauseFix
Google Drive returns no files Folder ID is empty or incorrect in the Search node Open the Google Drive node → Filter → Folder ID and enter your “pending” folder’s ID (copy from the Drive URL)
Cloudinary upload fails Google Drive webContentLink requires authentication Make sure the file in Drive is shared as “Anyone with the link can view” — Cloudinary needs a public download URL
OpenRouter returns an error Invalid or expired API key in the HTTP Header credential Check your OpenRouter API key at openrouter.ai/keys and update the n8n credential
Facebook Reel fails: “Invalid node” Facebook Page ID is still the placeholder Replace YOUR_FACEBOOK_PAGE_ID in the Facebook Graph API nodes with your actual Page ID (found in Meta Business Suite → Settings → Page Info)
Instagram publish fails: “The media container is not ready” 30-second wait wasn’t long enough for processing Increase the Wait node before “Upload to instagram” to 60 seconds for larger videos
YouTube upload returns 403 OAuth token expired or insufficient scopes Reconnect the YouTube OAuth2 credential in n8n, ensuring the youtube.upload scope is granted
Google Sheet not updating Column name mismatch (case-sensitive) Confirm your sheet headers match exactly: video_url, Video Caption, Status

Frequently Asked Questions

Do I need a paid Cloudinary plan for this to work?

No — Cloudinary’s free tier supports up to 25 GB of storage and 25 GB monthly bandwidth, which is plenty for most small to medium posting schedules. If you’re posting long-form videos or several per day, upgrade to a paid plan. The secure_url generated for each upload never expires, so your CDN links remain valid indefinitely.

Can I change the AI model that generates captions?

Yes. The “video Caption” node is a standard HTTP Request to OpenRouter. Change the model field in the JSON body to any OpenRouter-supported model — for example, openai/gpt-4o-mini for lower cost or meta-llama/llama-3-70b-instruct for an open-source option. The system prompt and output format stay the same regardless of model.

Why does the workflow use Cloudinary instead of uploading directly from Drive?

Facebook and Instagram’s APIs require a publicly accessible video URL that their servers can download. Google Drive download links require authentication and have rate limits. Cloudinary solves both problems: it fetches the file from Drive during upload and serves it via a clean, public CDN URL that all four platforms can reliably access. It also handles transcoding and format compatibility automatically.

Can this post to TikTok automatically too?

The workflow currently stages TikTok data in a separate sheet tab (video URL + caption) but doesn’t publish directly, because TikTok’s Content Posting API requires business account approval and has stricter OAuth flows. The staged row is ready to wire into a TikTok API node once you have access — or you can use a tool like Buffer or Later to pick up from that sheet.

What happens if the workflow runs and there’s no video in the Drive folder?

The Google Drive “Search files and folders” node will return an empty result set, and the workflow will stop at that point with no error — it simply has nothing to process. No rows will be updated, no API calls will be made. You can optionally add an IF node after the Drive search to send yourself a Telegram or email notification when no videos are found.

Can I post to multiple Facebook Pages or Instagram accounts?

Yes, but you’ll need a separate set of Facebook Graph API nodes for each page or account, each with its own credential. The cleanest approach is to duplicate the Facebook and Instagram sections of the workflow and swap the Page ID and Instagram User ID in the cloned nodes. One n8n workflow can handle multiple accounts in parallel using a Split In Batches node at the top.

🚀 Get the Social Media Automation Template

Download the ready-to-import workflow JSON, the Google Sheets setup template with both tabs pre-configured, and a step-by-step credential guide — everything you need to go from zero to cross-platform posting in under 20 minutes.

Get the Template →

Instant download · Works on n8n Cloud and self-hosted

What’s Next?

  • Add a Telegram alert — wire a Telegram node at the very end to send yourself a confirmation message with the video title and publish status every time a video goes live.
  • Schedule multiple posts per day — duplicate the workflow and set one trigger for 9 AM and another for 6 PM to double your daily output without any extra manual work.
  • Auto-generate video thumbnails — add a Cloudinary transformation step that extracts a frame from the uploaded video and creates a custom thumbnail you can use as the YouTube cover image.
  • Connect a content calendar — replace the manual “add a file to Drive” step with a Notion or Airtable database where you queue up video ideas, titles, and target dates, and let the workflow pick the next scheduled entry automatically.
  • Add TikTok direct posting — once your TikTok Content Posting API access is approved, add a TikTok node after the “Append row in sheet” step and close the loop on all five platforms in a single run.
n8n Social Media Automation Instagram Reels Facebook Reels YouTube Automation Cloudinary Google Drive OpenRouter AI Caption Generator No Code

How to Build an AI Customer Service Chatbot for Your WooCommerce Store with n8n

How to Build an AI Customer Service Chatbot for Your WooCommerce Store with n8n

A multilingual AI agent that answers product questions, collects orders conversationally, and logs every buyer to Google Sheets — fully automated, zero code.

Running an online store means fielding the same questions at all hours — “Do you have this in my size?”, “How much does shipping cost?”, “Can I order online?” Every answer is manual, every missed message is a lost sale. This n8n workflow replaces that cycle with a multilingual AI agent that knows your entire WooCommerce product catalog in real time, handles customer conversations in Arabic, English, or French, collects order details when a buyer is ready, and writes everything to a Google Sheet for your fulfillment team — without you lifting a finger.

Prefer to skip the setup? Grab the ready-made template → and be up and running in under 10 minutes.

What You’ll Build

  1. A customer opens your store’s chat widget and sends a message — the agent immediately asks which language they prefer (Arabic, English, or French).
  2. The AI queries your live WooCommerce product catalog in real time before answering any product question — it never guesses or invents details.
  3. If a product isn’t in stock, the agent politely asks whether the customer would like you to source it, then waits for a response.
  4. When the customer is ready to order, the agent collects their name, email, phone, address, country, and item through natural conversation — no form required.
  5. The order details are automatically appended to a Google Sheet row, ready for your fulfillment team to action.

How It Works — The Big Picture

The workflow has a single entry point — the n8n Chat Trigger — and routes every incoming message through an input guard before passing it to the AI agent. The agent has four tools it can call autonomously: a live product lookup, a Google Sheets writer, a calculator, and a “Think” reasoning step.

┌──────────────────────────────────────────────────────────────────────┐
│  AI ECOMMERCE CHATBOT (n8n)                                          │
│                                                                      │
│  [Chat Trigger] ──► [If: chatInput exists?]                         │
│                              │                                       │
│               ┌──────────────┴──────────────┐                       │
│            true (has input)             false (empty)               │
│               │                              │                       │
│               ▼                              ▼                       │
│      [Store Manager AI Agent]     [Respond to Webhook]              │
│       ┌───────┴────────┐          "How can I assist you?"           │
│       │   AI Tools:    │                                             │
│       │ • Get Products │ ◄── Live WooCommerce product data          │
│       │ • Customer DB  │ ──► Append row to Google Sheets            │
│       │ • Calculator   │ ◄── Price / quantity math                  │
│       │ • Think        │ ◄── Internal reasoning step                │
│       └───────┬────────┘                                             │
│               ▼                                                      │
│      [Respond to Webhook 1] ──► Customer sees AI reply in chat      │
└──────────────────────────────────────────────────────────────────────┘

What You’ll Need

  • n8n — self-hosted or n8n Cloud (any recent version)
  • WooCommerce store with REST API enabled and API keys generated
  • OpenRouter account — free tier available; choose your LLM (GPT-4o, Claude, Llama, etc.)
  • Google account with a Sheets spreadsheet set up as the customer database
  • A front-end chat widget that POSTs to an n8n webhook (the built-in n8n chat UI works out of the box)

Estimated build time: 45–60 minutes from scratch, or under 10 minutes with the ready-made template.

Part 1 — Receiving and Validating the Message

1 When Chat Message Received (Chat Trigger)

This is the entry point of the entire workflow. n8n’s built-in Chat Trigger node opens a publicly accessible webhook endpoint and provides a ready-made chat UI you can embed anywhere. Every customer message fires this node and passes two fields downstream: chatInput (the message text) and sessionId (a unique ID tying all messages in one conversation together).

Set Public to true so the chat interface is accessible without authentication. Leave Initial Messages blank — the AI will send the first language-selection greeting itself.

// Data shape from the Chat Trigger
{
  "chatInput": "Do you carry trail running shoes?",
  "sessionId": "user_a8f3k2"
}
💡

Tip: Embed the widget on your store by copying the script URL from the Chat Trigger node and adding it to your theme’s footer. No plugin required.

2 If — Guard Against Empty Input

Browser pre-flight requests and widget load events can hit your webhook with an empty body. This If node checks whether $json.chatInput exists. If it does, the message goes to the AI agent. If not, a friendly default response fires immediately — no wasted tokens, no errors.

📌

Note: The condition uses strict type validation and checks for exists, correctly handling null, undefined, or a missing key — all of which would otherwise crash the agent.

Part 2 — The Store Manager AI Agent

3 Store Manager (AI Agent)

The Store Manager is the brain of the workflow — an n8n AI Agent node that reads the customer’s message, decides which tools to call, executes them, and formulates a natural-language response. Its entire behavior is controlled by the system prompt, which you can customize directly in the node settings.

The system prompt instructs the agent to:

  • Always open by asking for the customer’s preferred language (Arabic, English, or French)
  • Respond only in the chosen language for the rest of the conversation
  • Never invent product details — always call Get Products first
  • Collect order information conversationally only after the customer expresses intent to buy
  • Keep responses short and human — no JSON, no bullet lists unless asked
💡

Tip: The system prompt references the store name “MoroccoVibe”. Replace it with your own store name so the agent introduces itself correctly on the very first message.

4 OpenRouter (Language Model)

OpenRouter routes the agent to 100+ LLM providers. Switch between GPT-4o, Claude Sonnet, Mistral, Llama 3, and more by changing a single dropdown — no other configuration needed. Add your OpenRouter API key in the credentials panel.

💡

Tip: For customer service, Claude 3 Haiku or GPT-4o Mini offer excellent quality at very low cost — typically under $0.01 per full conversation.

5 Simple Memory (Session Buffer)

The Simple Memory node gives the agent a 20-message conversation window keyed to each sessionId, so every customer’s chat is isolated and contextual. When a customer says “the second one you mentioned” four messages later, the agent knows exactly what they mean.

{
  "sessionKey": "{{ $json.sessionId }}",
  "contextWindowLength": 20
}

6 Get Products (WooCommerce Tool)

This tool gives the agent live, read-only access to your WooCommerce catalog. Whenever a customer asks about a product, the agent calls this tool automatically before answering — no hardcoded product lists, always fresh data. Connect your WooCommerce API credentials (Consumer Key + Consumer Secret) found under WooCommerce → Settings → Advanced → REST API.

📌

Note: If your store has more than 100 products, filter by search term rather than returning everything — fetching the full catalog on every message adds latency and increases token cost.

7 Customer Database (Google Sheets Tool)

Once the agent has collected all six required fields, it calls this tool to append a new row to your Google Sheet. Column values are written using $fromAI() expressions — the agent extracts each field from the conversation context and maps it directly, no manual field setup needed beyond the initial schema.

8 Think & Calculator (Reasoning Tools)

Think lets the agent reason internally before complex answers — useful for matching vague product descriptions or deciding whether to ask a clarifying question. Calculator handles all arithmetic (totals, discounts, unit quantities) to guarantee exact results and avoid LLM number drift.

The Data Structure

Create a Google Sheet with these exact column names before activating the workflow. The names are case-sensitive — the agent uses them as keys when writing rows.

Column NameTypeExample ValueDescription
Items NameTextTrail Running Shoe — Size 10Product(s) the customer wants to order
Full NameTextJames CarterCustomer’s full name as provided in chat
Home addressText742 Evergreen Terrace, Springfield, IL 62704Full delivery address
Email AdresseTextjames.carter@gmail.comMatching key — prevents duplicate rows
Phone NumberText(555) 867-5309Contact number for delivery follow-up
CountryTextUnited StatesDestination country for shipping
NoteTextPrefers express shippingExtra notes from conversation (note the leading space in the column name)
📌

Important: Email Adresse is the matching key — a second submission with the same email updates the existing row instead of creating a duplicate. The Note column has a leading space; keep this exactly as shown.

Full System Flow

Customer types in chat widget
          │
          ▼
[Chat Trigger] → { chatInput: "Do you carry trail running shoes?", sessionId: "user_a8f3k2" }
          │
          ▼
[If: chatInput exists?]
    │ true                            │ false
    ▼                                 ▼
[Store Manager Agent]       [Respond to Webhook] → "How can I assist you today?"
    │
    ├──► [Think] ← reasons about customer intent
    ├──► [Get Products] ← live WooCommerce catalog query
    │      └─ returns: [{ name: "Trail Runner Pro", price: "$89.00", stock: "In stock" }]
    ├──► (customer wants to order)
    │      [Customer Database] ← appends Google Sheet row:
    │        James Carter | james.carter@gmail.com | (555) 867-5309 | Springfield, IL | Trail Runner Pro
    └──► [Calculator] ← exact price/quantity arithmetic
          │
          ▼
[Respond to Webhook 1] → AI reply delivered to customer chat

Testing Your Workflow

  1. Click Test workflow in n8n, then open the Chat Trigger node and click Open Chat to launch the built-in test interface.
  2. Send “Hello” — verify the agent responds asking for language preference.
  3. Reply “English”, then ask about a real product in your WooCommerce store. Confirm the agent returns accurate, live data.
  4. Say “I’d like to buy it” and walk through the information collection. Verify all six fields are captured correctly.
  5. Open your Google Sheet and confirm a new row was appended with the correct data.
  6. Send an empty message to confirm the fallback route fires the default greeting.
ProblemLikely CauseFix
Agent says “I don’t have that information” WooCommerce API key has insufficient scope Ensure the key has Read access to products under WooCommerce → Settings → REST API
Google Sheet row not created Column names don’t match schema exactly Compare headers character-by-character, including the leading space in Note
Agent forgets earlier messages Session ID not passing through correctly Confirm the Chat Trigger is set to Public and sessionId is present in the payload
Agent responds in the wrong language Language wasn’t chosen on the first message Clear session memory and start a fresh conversation — language selection must happen on message #1
No response in the chat widget Webhook response format mismatch Check that Respond to Webhook 1 is set to allIncomingItems

Frequently Asked Questions

Can I use a different AI model instead of OpenRouter?

Yes. The OpenRouter node is interchangeable with any n8n-supported language model — OpenAI, Anthropic, Google Gemini, Mistral, and others all work as drop-in replacements. Just swap the model node on the agent’s Chat Model input and reconnect the credential. Nothing else changes.

What languages does the chatbot support?

Out of the box: Arabic, English, and French. Add or remove languages by editing the list in the Store Manager system prompt — the AI handles the rest as long as your chosen LLM supports those languages, which most modern models do.

Will the agent handle multiple customers simultaneously?

Yes. Each conversation is isolated by its sessionId. The Simple Memory node stores history per session key, so 50 simultaneous customers each get their own private conversation context with no cross-contamination.

What happens if a customer submits their info twice?

Since Email Adresse is the matching key, a second submission with the same email updates the existing row rather than creating a duplicate — keeping your sheet clean even if a customer changes their order details mid-conversation.

Does this work with WooCommerce variable products (sizes, colors)?

The Get Products node fetches product data including variations when available via the WooCommerce API. For more complex variant selection, consider adding a second WooCommerce node that fetches variations by product ID once the customer has chosen a base product.

Is the chat widget included in the template?

The n8n Chat Trigger provides a built-in widget accessible via a unique URL — embed it in your WooCommerce theme as an iframe or script. Any front-end chat library that POSTs JSON to a webhook URL also works: Tidio, Crisp, or a fully custom implementation.

🚀 Get the AI Ecommerce Chatbot Template

Download the ready-to-import workflow JSON, the Google Sheets setup template, and a step-by-step credential guide — everything you need to go live in under 10 minutes.

Get the Template →

Instant download · Works on n8n Cloud and self-hosted · 14-day refund guarantee

What’s Next?

  • Order confirmation emails — add a Gmail node after the Sheets tool to send an automated confirmation to the customer’s email the moment their details are saved.
  • Slack fulfillment alerts — ping your team channel with the customer name and item every time a new order row is created.
  • Inventory warnings — extend the WooCommerce tool call to check stock levels and proactively warn customers when an item is running low.
  • Multi-store support — duplicate the workflow and swap credentials to run the same agent for multiple storefronts, each with its own brand persona in the system prompt.
n8n WooCommerce AI Agent Google Sheets OpenRouter Customer Service Ecommerce Automation Multilingual Chatbot No Code