Gmail + Google Sheets: promo sends logged clean
You send a promo. It bounces. Or worse, it “delivers” but goes nowhere, and you have no clean record of who got what. Then you’re digging through Gmail threads and half-finished spreadsheets trying to prove a campaign actually ran.
This Gmail Sheets logging setup hits marketing managers first, honestly. But store owners running weekly promos and agency teams delivering client campaigns feel it too. The outcome is simple: verified emails, a polished offer, and a spreadsheet log you can trust for follow-ups.
Below is the workflow that verifies each address, generates a personalized QR promo card, sends it through Gmail, and records the send to Google Sheets (with an error path that alerts you when something’s off).
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Gmail + Google Sheets: promo sends logged clean
flowchart LR
subgraph sg0["Flow 1"]
direction LR
n0["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/webhook.dark.svg' width='40' height='40' /></div><br/>Incoming Signup Webhook"]
n1@{ icon: "mdi:swap-vertical", form: "rounded", label: "Map Input Details", pos: "b", h: 48 }
n2@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Verify Email Address", pos: "b", h: 48 }
n3@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Branch on Validity", pos: "b", h: 48 }
n4@{ icon: "mdi:cog", form: "rounded", label: "Render Promo Card", pos: "b", h: 48 }
n5@{ icon: "mdi:message-outline", form: "rounded", label: "Send Promo Email", pos: "b", h: 48 }
n6@{ icon: "mdi:database", form: "rounded", label: "Record Promo Log", pos: "b", h: 48 }
n7@{ icon: "mdi:swap-vertical", form: "rounded", label: "Assemble Error Info", pos: "b", h: 48 }
n8@{ icon: "mdi:message-outline", form: "rounded", label: "Notify Admin Failure", pos: "b", h: 48 }
n0 --> n1
n1 --> n2
n5 --> n6
n7 --> n8
n2 --> n3
n3 --> n4
n3 --> n7
n4 --> n5
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n2,n3 decision
class n6 database
class n0 api
classDef customIcon fill:none,stroke:none
class n0 customIcon
The Problem: Promo emails turn into a tracking mess
Promo delivery sounds straightforward until you’re doing it at volume. You export a list, spot-check a few emails, paste names into a template, send, then hope your list quality doesn’t torch deliverability. When bounces happen, you’re stuck cleaning your data after the fact. And even when everything “works,” you still need a reliable record for support requests (“I didn’t get my code”), for attribution (“who redeemed what”), and for follow-ups (“resend to valid-but-unopened”). Manually, that tracking never stays clean for long.
The friction compounds. Here’s where it breaks down in real life.
- Bad emails sneak in, which means bounces, wasted sends, and lower sender reputation over time.
- Personalization becomes copy-paste work, so campaigns ship late or go out with obvious mistakes.
- Creative assets (like a QR promo card) take longer than the email itself, so you skip them even when they boost conversions.
- Logging is inconsistent, so follow-ups are guesswork and reporting becomes “close enough.”
The Solution: Verify, generate, send, and log in one run
This workflow turns promo distribution into a single, repeatable process you can trust. It starts when new user data hits an n8n webhook (name, email, promo code, and discount details). n8n formats the inputs, fills in sensible defaults when fields are missing, then checks the email address with Verifi Email API before anything gets sent. If the email is valid, the workflow generates a personalized promo card image using an HTML/CSS-to-image service (including a QR code for redemption) and emails it through Gmail as a polished HTML message. Finally, it logs the successful send into Google Sheets so you have an audit trail for follow-ups, reporting, and support.
If the email fails verification, it does not attempt delivery. Instead, the workflow assembles a clean error payload and alerts an admin via Gmail so you can fix the source data or investigate suspicious activity. Quiet failures are the enemy, and this avoids them.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you send 50 promo codes after a contest. Manually, even a “quick” flow is roughly 5 minutes per person (verify the email, generate an asset, send, then log it), which is about 4 hours. With this workflow, you trigger sends in bulk from your source system and each request typically finishes in about a minute (the workflow’s own benchmark is 30–60 seconds). You still monitor results, but the busywork is gone, and the sheet is updated automatically as each email succeeds.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Gmail to send the promo email.
- Google Sheets to store a clean send log.
- Verifi Email API key (get it from verifi.email dashboard).
- HTML/CSS to Image API key (get it from htmlcsstoimg.com).
Skill level: Intermediate. You’ll connect credentials, paste in a Sheet ID, and tweak a template or two without breaking the logic.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
A signup or campaign event hits a webhook. Your form, store, or campaign tool sends a POST request with name, email, and promo details when someone qualifies.
The input is cleaned and normalized. n8n maps fields, applies default values (like a fallback promo code), and prepares a consistent payload so the rest of the flow doesn’t get brittle.
Email verification decides the path. Verifi checks if the address is valid. If it passes, the workflow continues. If not, it routes to an error branch that assembles the reason and notifies an admin.
A promo card is generated, then Gmail sends the email. The HTML/CSS-to-image service renders your branded card as a PNG, including a QR code, and Gmail delivers a polished HTML message with the card embedded.
Logging happens immediately after a successful send. Google Sheets receives a row with timestamp, recipient details, promo values, and send status so you can filter, segment, and follow up later.
You can easily modify the card design to match your brand or swap the redemption link based on campaign. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Webhook Trigger
This workflow starts when a signup form posts to the webhook, which then maps incoming fields for downstream use.
- Add and open Incoming Signup Webhook, then set HTTP Method to
POST. - Set Path to
promo-signup. - In Options → Response Data, set the JSON response to
{"status": "success", "message": "Promo card being generated!"}. - Open Map Input Details and define fields using expressions: name =
{{$json.body.name || 'Valued Customer'}}, email ={{ $json.body.email }}, promo_code ={{ $json.body.promo_code || 'WELCOME10'}}, discount_value ={{ $json.body.discount_value || '10%' }}, discount_type ={{ $json.body.discount_type || 'percentage' }}, timestamp ={{new Date().toISOString()}}.
body (e.g., body.email). If the payload shape differs, update the expressions in Map Input Details.Step 2: Connect Google Sheets
Successful sends are logged to a spreadsheet for tracking.
- Open Record Promo Log and set Operation to
append. - Select the Google Sheet by setting Document ID to
YOUR_GOOGLE_SHEETS_IDand Sheet Name toSheet1(gid=0). - Map columns with expressions: Name =
{{ $('Map Input Details').item.json.name }}, Email ={{ $('Map Input Details').item.json.email }}, Status =Sent Successfully, Timestamp ={{new Date().toISOString()}}, Promo Code ={{ $('Map Input Details').item.json.promo_code }}, Discount Value ={{ $('Map Input Details').item.json.discount_value }}. - Credential Required: Connect your googleSheetsOAuth2Api credentials in Record Promo Log.
Step 3: Set Up Verification and Card Rendering
The workflow verifies the email and only generates a promo card for valid addresses.
- Open Verify Email Address and set Email to
{{ $json.email }}. - Credential Required: Connect your verifiEmailApi credentials in Verify Email Address.
- Configure Branch on Validity with the condition: Left Value =
{{ $json.valid }}, Operation =equals, Right Value =true. - Open Render Promo Card and set Response Format to
png; keep the provided HTML in HTML Content so it references{{ $('Map Input Details').item.json.name }},{{ $('Map Input Details').item.json.discount_value }}, and{{ $('Map Input Details').item.json.promo_code }}. - Credential Required: Connect your htmlcsstoimgApi credentials in Render Promo Card.
YOURSTORE.com. Replace it with your actual store domain before going live.Step 4: Configure Output Email and Logging
Once the promo card is rendered, the workflow sends the email and records the delivery in Sheets.
- Open Send Promo Email and set Send To to
{{ $('Map Input Details').item.json.email }}. - Set Subject to
🎉 Your Exclusive {{ $('Map Input Details').item.json.discount_value }} Discount is Ready!. - In Message, keep the HTML template and ensure the promo card image uses
{{ $json.image_url }}. - Credential Required: Connect your gmailOAuth2 credentials in Send Promo Email.
- Confirm the execution order: Render Promo Card → Send Promo Email → Record Promo Log.
Step 5: Add Error Handling
Invalid emails are routed to a notification path that alerts an admin.
- On the Branch on Validity false path, configure Assemble Error Info to set error_type =
Invalid Email, timestamp ={{new Date().toISOString()}}, and email ={{ $('Map Input Details').item.json.email }}. - Open Notify Admin Failure and set Send To to
[YOUR_EMAIL]. - Set Subject to
⚠️ Failed Promo Card Generationand Message toFailed to generate promo card for {{ $('Map Input Details').item.json.email }} - Invalid email address. - Credential Required: Connect your gmailOAuth2 credentials in Notify Admin Failure.
Step 6: Test and Activate Your Workflow
Run a full end-to-end test to verify emails are validated, cards rendered, and logs recorded.
- Click Execute Workflow and send a test POST request to Incoming Signup Webhook with a valid email.
- Confirm Verify Email Address returns
valid: true, Render Promo Card outputsimage_url, and Send Promo Email sends the message. - Check Record Promo Log to ensure the row is appended with the correct fields and timestamp.
- Test an invalid email and confirm the false path runs: Assemble Error Info → Notify Admin Failure.
- When everything looks correct, toggle the workflow to Active for production use.
Common Gotchas
- Google Sheets access fails more often than you’d think because the sheet wasn’t shared with the right account. If logging breaks, check the Sheet sharing settings and the credential used by the Google Sheets node first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Frequently Asked Questions
About an hour if your Google credentials are ready.
No. You’ll connect accounts and paste in a few IDs and keys. The only “technical” part is minor template tweaks if you want your own branding.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in Verifi Email API costs and HTML/CSS to Image API costs based on usage.
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, and it’s the fun part. You’ll mainly customize the “Render Promo Card” step by editing the HTML/CSS (colors, layout, logo, QR size, and the validity date). Common tweaks include swapping the checkout URL in the QR code, changing the discount badge to match fixed-amount offers, and updating the email subject line inside the “Send Promo Email” step.
Most of the time it’s OAuth permission trouble or an expired token. Reconnect the Gmail credential in n8n, then confirm the Gmail API is enabled in your Google Cloud project. Also check you’re sending “from” an address your connected Gmail account is actually allowed to use.
It’s built for volume: the workflow notes “hundreds of requests per hour,” and it usually completes each request in about a minute. On n8n Cloud, your limit is mostly plan-based executions per month, plus the API limits of Verifi and your image renderer. If you self-host, the practical ceiling is your server capacity and how fast you want to send without tripping Gmail rate limits.
For this specific flow, n8n is a better fit when you care about branching logic (valid vs invalid), templated asset rendering, and having a real error path that notifies you. Zapier and Make can do parts of it, but the cost and complexity climb once you add verification, image generation, and robust logging. If you’re only sending a basic email and writing one row to a sheet, those tools can be simpler. The minute you want control, n8n wins. Talk to an automation expert if you want help choosing.
Once this is live, promo delivery stops being a scramble and starts being a system. The workflow handles verification, presentation, and tracking so you can focus on the offer and the next follow-up.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.