This workflow corresponds to n8n.io template #10384 — we link there as the canonical source.
This workflow follows the Emailsend → Google Sheets recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "uqNyk0asIuKnQMXk",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Send feedback survey to canceled Stripe subscriptions",
"tags": [],
"nodes": [
{
"id": "52bde91d-175a-49dd-8a41-7d35b8fcbc58",
"name": "Workflow Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1104,
0
],
"parameters": {
"width": 640,
"height": 1340,
"content": "## \ud83d\udccb Automated Feedback Survey on Stripe Cancellation\n\n**What this workflow does:**\n\nWhen a customer cancels their Stripe subscription, this workflow automatically:\n\n1. \u2705 Detects the cancellation event via Stripe webhook\n2. \u2705 Fetches customer email and name from Stripe API\n3. \u2705 Sends a personalized feedback survey email with embedded customer data\n4. \u2705 Logs cancellation details to Google Sheets\n5. \u2705 Receives survey responses via webhook\n6. \u2705 Routes feedback to different sheets based on reason (Price/Features/Other)\n\n**Why it matters:**\n\nUnderstanding why customers leave is critical for reducing churn. This workflow ensures you never miss collecting valuable cancellation feedback and organizes it automatically for actionable insights.\n\n**Setup time:** ~20 minutes\n\n**Compatible survey tools:** Tally, Typeform, or any tool with webhook support\n\n---\n\n## \ud83d\udd27 Setup Steps\n\n### 1. Connect Your Stripe Account\n- Use test mode for initial setup\n- Copy the webhook URL from the \"Stripe Subscription Canceled\" node\n- Add it to your Stripe Dashboard \u2192 Webhooks\n- Select event: `customer.subscription.deleted`\n\n### 2. Configure Email Credentials\n- Set up Gmail, Outlook, or SMTP credentials\n- Update the \"from\" email address in the send email node\n\n### 3. Create Your Survey Form\nYour survey form needs these fields:\n- **Hidden fields** (populated from URL parameters):\n - email\n - customer_id\n - name\n - plan\n- **Visible fields:**\n - Reason dropdown (\"Too Expensive\", \"Missing Features\", \"Other\")\n - Comments textarea\n\n### 4. Configure Survey Webhook\n- Get the webhook URL from the \"Survey Response Webhook\" node\n- Configure your survey tool to POST responses to this URL\n- Ensure the payload includes: email, customer_id, name, plan, reason, comments\n\n### 5. Set Up Google Sheets\nCreate a Google Sheets document with 4 sheets:\n- **Cancellations** (main log of all cancellations)\n- **Price Concerns** (for price-related feedback)\n- **Feature Requests** (for feature-related feedback)\n- **Other Feedback** (for everything else)\n\n### 6. Update Survey URL\nReplace `[SURVEY_URL]` in the email template with your actual survey link\n\n---\n\n## \ud83d\udca1 Customization Ideas\n\n- Add **Slack notification** for real-time alerts on price concerns\n- Use **IF node** to send different surveys based on subscription tier\n- Add **Wait node** to delay email by 24 hours\n- Add **urgent flag** for high-value customer cancellations\n- Integrate with your CRM for follow-up workflows\n\n---\n\n## \ud83d\udcca What Gets Logged\n\n**Cancellations sheet:**\n- Cancellation timestamp\n- Customer ID, email, name\n- Plan name\n- Email send status\n\n**Feedback sheets (organized by reason):**\n- Response timestamp\n- Customer details\n- Cancellation reason\n- Additional comments\n\n---\n\n## \ud83c\udfaf Benefits\n\n- **Reduce churn** by understanding why customers leave\n- **Prioritize** product improvements based on organized feedback\n- **Automate** the entire feedback collection process\n- **Track** which plans have the highest cancellation rates"
},
"typeVersion": 1
},
{
"id": "fd82e2f9-248f-409f-a790-ec00ca02ca1c",
"name": "Step 1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-368,
0
],
"parameters": {
"color": 7,
"width": 360,
"height": 280,
"content": "## Step 1: Detect Cancellation\n\nListens for `customer.subscription.deleted` webhook event from Stripe.\n\n**Setup:**\n- Connect your Stripe account\n- Copy the webhook URL from this node\n- Add it to Stripe Dashboard \u2192 Webhooks\n- Select event: customer.subscription.deleted"
},
"typeVersion": 1
},
{
"id": "c4b72f4a-32e3-4736-9a8b-896b775ffbc7",
"name": "Step 2",
"type": "n8n-nodes-base.stickyNote",
"position": [
16,
48
],
"parameters": {
"color": 7,
"width": 340,
"height": 240,
"content": "## Step 2: Get Customer Info\n\nFetches customer email and name from Stripe API.\n\n**Why needed:**\nThe webhook event doesn't include email directly - we must fetch it separately for the survey email and URL parameters."
},
"typeVersion": 1
},
{
"id": "4e99664a-7ba0-43d2-8f70-d6d4be8ac7fe",
"name": "Step 3",
"type": "n8n-nodes-base.stickyNote",
"position": [
368,
-272
],
"parameters": {
"color": 7,
"width": 380,
"height": 560,
"content": "## Step 3: Send Survey Email\n\n**IMPORTANT: Survey URL Setup**\n\nThe survey URL includes customer data as parameters:\n`[SURVEY_URL]?email={email}&customer_id={id}&name={name}&plan={plan}`\n\n**Required setup:**\n1. Enter your **From Email** address\n2. Configure email credentials (Gmail/Outlook/SMTP)\n3. Replace `[SURVEY_URL]` with your actual survey link\n4. Configure your survey form to:\n - Accept URL parameters (email, customer_id, name, plan)\n - Store them as hidden fields\n - Send data to webhook when submitted\n\n**Supported survey tools:**\n- Tally (has webhook)\n- Typeform (has webhook)\n- Custom form with webhook"
},
"typeVersion": 1
},
{
"id": "0862a1bf-a237-4516-bccc-7eecdda7cf0f",
"name": "Step 4",
"type": "n8n-nodes-base.stickyNote",
"position": [
800,
-112
],
"parameters": {
"color": 7,
"width": 360,
"height": 400,
"content": "## Step 4: Log Cancellation\n\n**Setup:**\n- Select your Google Sheets document\n- Sheet name: \"Cancellations\"\n- Headers created automatically on first run\n\n**Columns logged:**\n- Cancellation timestamp\n- Customer ID, email, name\n- Plan name\n- Email send status\n\nThis logs every cancellation regardless of survey response."
},
"typeVersion": 1
},
{
"id": "4ed549f9-81e1-4f84-978e-2aba193ca509",
"name": "Step 5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-384,
944
],
"parameters": {
"color": 7,
"width": 380,
"height": 460,
"content": "## Step 5: Receive Survey Response\n\n**SEPARATE WORKFLOW TRIGGER**\n\nThis webhook activates when a customer submits the survey.\n\n**Survey form webhook setup:**\n- Configure webhook to POST to this URL\n- Include these fields in webhook payload:\n - email\n - customer_id\n - name\n - plan\n - reason (\"Too Expensive\", \"Missing Features\", \"Other\")\n - comments\n\n**Test webhook:**\nUse the \"Listen for Test Event\" feature to test with sample data"
},
"typeVersion": 1
},
{
"id": "adbd2373-0271-4f10-bb73-a343510ab646",
"name": "Step 6",
"type": "n8n-nodes-base.stickyNote",
"position": [
16,
944
],
"parameters": {
"color": 7,
"width": 380,
"height": 460,
"content": "## Step 6: Route by Reason\n\nSorts feedback into 3 categories based on the \"reason\" field:\n\n**Output 0:** reason contains \"expensive\" or \"price\" or \"cost\"\n\u2192 Goes to \"Price Concerns\" sheet\n\n**Output 1:** reason contains \"feature\" or \"functionality\" or \"missing\"\n\u2192 Goes to \"Feature Requests\" sheet\n\n**Output 2:** Everything else\n\u2192 Goes to \"Other Feedback\" sheet\n\n**Customize:**\nEdit the Switch node conditions to match your survey options"
},
"typeVersion": 1
},
{
"id": "2f712d4a-b1fb-403a-9818-cdedbfce2500",
"name": "Step 7",
"type": "n8n-nodes-base.stickyNote",
"position": [
416,
944
],
"parameters": {
"color": 7,
"width": 440,
"height": 500,
"content": "## Step 7: Log to Category Sheets\n\n**Create 3 sheets in your Google Sheets:**\n\n1. **Price Concerns** - for pricing issues\n2. **Feature Requests** - for missing features\n3. **Other Feedback** - for everything else\n\n**Each logs:**\n- Response timestamp\n- Customer email, name\n- Plan name\n- Cancellation reason\n- Additional comments\n\nThis organization helps you:\n- Prioritize pricing adjustments\n- Plan product roadmap\n- Understand other churn factors"
},
"typeVersion": 1
},
{
"id": "24749ad3-95c9-4d7d-a8a5-1e39c5257909",
"name": "Stripe Subscription Canceled",
"type": "n8n-nodes-base.stripeTrigger",
"position": [
-240,
320
],
"parameters": {
"events": [
"customer.subscription.deleted"
]
},
"typeVersion": 1
},
{
"id": "c553c09e-5f4c-44d0-979b-344191c6c3b4",
"name": "Get Customer Details",
"type": "n8n-nodes-base.stripe",
"position": [
112,
320
],
"parameters": {
"resource": "customer",
"customerId": "={{ $json.data.object.customer }}"
},
"typeVersion": 1
},
{
"id": "a4f93441-e29b-494d-a69c-d3bfd5695448",
"name": "Send Feedback Survey Email",
"type": "n8n-nodes-base.emailSend",
"position": [
480,
320
],
"parameters": {
"html": "=<p>Hi {{ $json.name || \"there\" }},</p>\n\n<p>Thank you for being a customer. We're sorry to see you go.</p>\n\n<p>To help us improve our service, would you mind sharing why you decided to cancel? It only takes 1 minute:</p>\n\n<p><a href=\"[SURVEY_URL]?email={{ $json.email }}&customer_id={{ $json.id }}&name={{ $json.name || 'Customer' }}&plan={{ $('Stripe Subscription Canceled').item.json.data.object.items.data[0].plan.nickname || $('Stripe Subscription Canceled').item.json.data.object.items.data[0].plan.id }}\" style=\"background-color: #4CAF50; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px; display: inline-block; margin: 16px 0;\">Share Your Feedback</a></p>\n\n<p><small>You were subscribed to: {{ $('Stripe Subscription Canceled').item.json.data.object.items.data[0].plan.nickname || 'Your Plan' }}</small></p>\n\n<p>Your feedback means the world to us and will help us serve our customers better.</p>\n\n<p>Thank you,<br>[Your Company Name]</p>\n\n<p><small>If you have any questions, feel free to reply to this email.</small></p>",
"options": {},
"subject": "We're sorry to see you go \u2014 Quick 1-min survey",
"toEmail": "={{ $json.email }}",
"fromEmail": "user@example.com"
},
"typeVersion": 2.1
},
{
"id": "cc898a60-e1af-4a6c-b26a-fbd53a88cba3",
"name": "Log to Cancellations Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
832,
320
],
"parameters": {
"columns": {
"value": {
"Plan Name": "={{ $('Stripe Subscription Canceled').item.json.data.object.items.data[0].plan.nickname || $('Stripe Subscription Canceled').item.json.data.object.items.data[0].plan.id }}",
"Email Sent": "={{ $('Send Feedback Survey Email').item.json.accepted ? 'Success' : 'Failed' }}",
"Customer ID": "={{ $('Stripe Subscription Canceled').item.json.data.object.customer }}",
"Customer Name": "={{ $('Get Customer Details').item.json.name || 'N/A' }}",
"Customer Email": "={{ $('Get Customer Details').item.json.email }}",
"Cancellation Date": "={{ new Date().toISOString() }}"
},
"schema": [
{
"id": "Cancellation Date",
"required": false,
"displayName": "Cancellation Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer ID",
"required": false,
"displayName": "Customer ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer Email",
"required": false,
"displayName": "Customer Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer Name",
"required": false,
"displayName": "Customer Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Plan Name",
"required": false,
"displayName": "Plan Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email Sent",
"required": false,
"displayName": "Email Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": []
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"typeVersion": 4.7
},
{
"id": "d4ad096a-addf-48c7-a693-fc07e30f1ed6",
"name": "Survey Response Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-240,
640
],
"parameters": {
"path": "survey-response",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "3077ceaa-38d5-4b20-b3f3-96c9c9587121",
"name": "Route by Feedback Type",
"type": "n8n-nodes-base.switch",
"position": [
112,
624
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "Price Concerns",
"conditions": {
"options": {
"caseSensitive": false
},
"combinator": "or",
"conditions": [
{
"operator": {
"type": "string",
"operation": "contains"
},
"leftValue": "={{ $json.reason }}",
"rightValue": "expensive"
}
]
},
"renameOutput": true
},
{
"outputKey": "Feature Requests",
"conditions": {
"options": {
"caseSensitive": false
},
"combinator": "or",
"conditions": [
{
"operator": {
"type": "string",
"operation": "contains"
},
"leftValue": "={{ $json.reason }}",
"rightValue": "feature"
}
]
},
"renameOutput": true
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"typeVersion": 3.2
},
{
"id": "5d3befc8-8831-42a2-9d83-0a81df2ab1f9",
"name": "Log Price Concerns",
"type": "n8n-nodes-base.googleSheets",
"position": [
480,
512
],
"parameters": {
"columns": {
"value": {
"Plan Name": "={{ $json.plan }}",
"Customer Name": "={{ $json.name }}",
"Response Date": "={{ new Date().toISOString() }}",
"Customer Email": "={{ $json.email }}",
"Additional Comments": "={{ $json.comments || 'N/A' }}",
"Cancellation Reason": "={{ $json.reason }}"
},
"schema": [
{
"id": "Response Date",
"required": false,
"displayName": "Response Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer Email",
"required": false,
"displayName": "Customer Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer Name",
"required": false,
"displayName": "Customer Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Plan Name",
"required": false,
"displayName": "Plan Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Cancellation Reason",
"required": false,
"displayName": "Cancellation Reason",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Additional Comments",
"required": false,
"displayName": "Additional Comments",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": []
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Price Concerns"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"typeVersion": 4.7
},
{
"id": "3c180c3d-c5e1-4a34-894b-973ac7cfe246",
"name": "Log Feature Requests",
"type": "n8n-nodes-base.googleSheets",
"position": [
480,
640
],
"parameters": {
"columns": {
"value": {
"Plan Name": "={{ $json.plan }}",
"Customer Name": "={{ $json.name }}",
"Response Date": "={{ new Date().toISOString() }}",
"Customer Email": "={{ $json.email }}",
"Additional Comments": "={{ $json.comments || 'N/A' }}",
"Cancellation Reason": "={{ $json.reason }}"
},
"schema": [
{
"id": "Response Date",
"required": false,
"displayName": "Response Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer Email",
"required": false,
"displayName": "Customer Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer Name",
"required": false,
"displayName": "Customer Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Plan Name",
"required": false,
"displayName": "Plan Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Cancellation Reason",
"required": false,
"displayName": "Cancellation Reason",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Additional Comments",
"required": false,
"displayName": "Additional Comments",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": []
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Feature Requests"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"typeVersion": 4.7
},
{
"id": "b09a3969-8253-4bac-94e7-b053a8fd48f1",
"name": "Log Other Feedback",
"type": "n8n-nodes-base.googleSheets",
"position": [
480,
784
],
"parameters": {
"columns": {
"value": {
"Plan Name": "={{ $json.plan }}",
"Customer Name": "={{ $json.name }}",
"Response Date": "={{ new Date().toISOString() }}",
"Customer Email": "={{ $json.email }}",
"Additional Comments": "={{ $json.comments || 'N/A' }}",
"Cancellation Reason": "={{ $json.reason }}"
},
"schema": [
{
"id": "Response Date",
"required": false,
"displayName": "Response Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer Email",
"required": false,
"displayName": "Customer Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer Name",
"required": false,
"displayName": "Customer Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Plan Name",
"required": false,
"displayName": "Plan Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Cancellation Reason",
"required": false,
"displayName": "Cancellation Reason",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Additional Comments",
"required": false,
"displayName": "Additional Comments",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": []
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Other Feedback"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": ""
}
},
"typeVersion": 4.7
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "36c00a3a-e28b-4d7b-9d2b-b1ae647da3ce",
"connections": {
"Get Customer Details": {
"main": [
[
{
"node": "Send Feedback Survey Email",
"type": "main",
"index": 0
}
]
]
},
"Route by Feedback Type": {
"main": [
[
{
"node": "Log Price Concerns",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Feature Requests",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Other Feedback",
"type": "main",
"index": 0
}
]
]
},
"Survey Response Webhook": {
"main": [
[
{
"node": "Route by Feedback Type",
"type": "main",
"index": 0
}
]
]
},
"Send Feedback Survey Email": {
"main": [
[
{
"node": "Log to Cancellations Sheet",
"type": "main",
"index": 0
}
]
]
},
"Stripe Subscription Canceled": {
"main": [
[
{
"node": "Get Customer Details",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Who's it for This template is perfect for any SaaS business or subscription service using Stripe. Product managers, customer success teams, and founders can use this to automatically collect cancellation feedback without manual follow-up. Ideal for companies looking to reduce…
Source: https://n8n.io/workflows/10384/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Supercharge your insurance agency's efficiency with this powerful automation template for n8n. Designed specifically for commercial insurance brokers and agents, this workflow transforms the tedious p
This template implements a professional Double Opt-In email verification system using Google Sheets as a database. The workflow collects user emails, generates unique verification codes, stores them s
This automation streamlines the process of collecting user information using a Form Node, enabling individuals to join a waitlist managed via Google Sheets.
Track website traffic and backlinks effortlessly using the Website Traffic Checker - Ahref API. This n8n workflow automates data retrieval and logging into Google Sheets, making it perfect for SEO pro
This powerful no-code workflow automates plagiarism detection using Plagiarism Checker AI Powered. Users submit text through Google Sheets. The system checks for duplication using the API, sends a det