This workflow corresponds to n8n.io template #17262 — we link there as the canonical source.
This workflow follows the Agent → 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": "JvFJ2REOLcJvdEj4",
"name": "Dynamic Pricing Recommendation Engine",
"tags": [],
"nodes": [
{
"id": "ea82a0d5-48a5-4632-a249-c31d87113248",
"name": "Main Sticky",
"type": "n8n-nodes-base.stickyNote",
"position": [
-16,
208
],
"parameters": {
"width": 732,
"height": 828,
"content": "## Dynamic Pricing Recommendation Engine\n\nThis workflow automates intelligent pricing recommendations for Salesforce Quotes by combining historical deal analysis with AI-driven decision-making.\n\n### How it works:\n\nThe workflow is triggered via a webhook whenever a new Quote event is received. It fetches related Opportunity and Account details from Salesforce to build complete deal context. This data is normalized and enriched with attributes such as deal size, segment, and industry.\n\nNext, historical deal data is loaded from Google Sheets and filtered to identify the most relevant past deals. A benchmarking layer computes key metrics such as win rate, average discounts, and safe pricing ranges.\n\nThese insights are passed to an AI pricing strategist, which generates an optimal discount, final price, win probability, confidence level, and justification. The output is structured and validated before updating the Quote record in Salesforce.\n\nFinally, a Slack notification is sent with a summary of the pricing recommendation for visibility and collaboration.\n\n### Setup steps:\n1. Configure Webhook node and connect it with Salesforce Quote trigger\n2. Set up Salesforce OAuth2 credentials for Opportunity and Account nodes\n3. Connect Google Sheets and ensure historical deal dataset is structured correctly\n4. Configure Groq/OpenAI credentials for AI nodes\n5. Verify field mappings for Quote update (discount, price, probability, etc.)\n6. Configure Slack credentials and select target user/channel\n7. Test workflow with sample Quote payload"
},
"typeVersion": 1
},
{
"id": "28381358-815a-4bab-b69f-43caadcdd4c6",
"name": "Section 1",
"type": "n8n-nodes-base.stickyNote",
"position": [
752,
464
],
"parameters": {
"color": 7,
"width": 624,
"height": 584,
"content": "## Trigger & CRM Context\n\nCaptures incoming Quote events and enriches them with Opportunity and Account data from Salesforce. This step builds the foundational deal context including deal amount, stage, customer type, and industry required for pricing decisions."
},
"typeVersion": 1
},
{
"id": "35964c89-a239-44d4-92c9-ef1ee82a281b",
"name": "Section 2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1392,
464
],
"parameters": {
"color": 7,
"width": 432,
"height": 584,
"content": "## Data Preparation & Enrichment\n\nTransforms raw CRM data into a structured format and loads historical deal records from Google Sheets. This prepares clean, consistent input for downstream analysis and AI processing."
},
"typeVersion": 1
},
{
"id": "7210c96b-08c8-4373-8fd5-3f813db8aae4",
"name": "Section 3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1840,
464
],
"parameters": {
"color": 7,
"width": 416,
"height": 584,
"content": "## Feature Engineering & Benchmarking\n\nFilters and ranks historical deals based on similarity to the current deal. Calculates win rates, discount trends, and safe pricing ranges to establish a strong analytical baseline."
},
"typeVersion": 1
},
{
"id": "cab20aae-b5a4-4bcb-9c1f-ef5062b99f00",
"name": "Section 4",
"type": "n8n-nodes-base.stickyNote",
"position": [
2272,
464
],
"parameters": {
"color": 7,
"width": 384,
"height": 584,
"content": "## AI Pricing Decision Engine\n\nUses AI to generate optimized pricing recommendations by combining deal context and historical insights. Outputs discount, final price, win probability, confidence level, and detailed justification."
},
"typeVersion": 1
},
{
"id": "2da09dde-65f8-4056-9693-312b36fed7f4",
"name": "Section 5",
"type": "n8n-nodes-base.stickyNote",
"position": [
2672,
464
],
"parameters": {
"color": 7,
"width": 916,
"height": 584,
"content": "## Execution, Update & Notification\n\nFormats AI output, updates Salesforce Quote fields, and sends a Slack notification. Ensures the recommendation is actionable, recorded, and communicated to stakeholders."
},
"typeVersion": 1
},
{
"id": "40dc8a05-d918-4286-9a6f-505d2d28dd42",
"name": "Quote Trigger (Webhook)",
"type": "n8n-nodes-base.webhook",
"position": [
784,
704
],
"parameters": {
"path": "dynamic-pricing-quote",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "9ed8d6d1-2163-4dc7-a8a7-4b9ba186dcf6",
"name": "Fetch Opportunity Details",
"type": "n8n-nodes-base.salesforce",
"position": [
1008,
704
],
"parameters": {
"resource": "opportunity",
"operation": "get",
"opportunityId": "={{ $json.body.opportunityId }}"
},
"typeVersion": 1
},
{
"id": "bf870ac2-8ed4-43a0-a7e2-491339cf0332",
"name": "Fetch Account Details",
"type": "n8n-nodes-base.salesforce",
"position": [
1232,
704
],
"parameters": {
"resource": "account",
"accountId": "={{ $json.AccountId }}",
"operation": "get"
},
"typeVersion": 1
},
{
"id": "74e6c716-3ad8-414f-8a1a-2d489c6f0358",
"name": "Normalize Deal Context",
"type": "n8n-nodes-base.code",
"position": [
1456,
704
],
"parameters": {
"jsCode": "function getDealSize(amount) {\n if (!amount) return \"unknown\";\n if (amount < 5000) return \"small\";\n if (amount < 20000) return \"medium\";\n return \"large\";\n}\n\n// Helper: normalize customer segment\nfunction getCustomerSegment(type) {\n if (!type) return \"unknown\";\n const t = type.toLowerCase();\n if (t.includes(\"enterprise\")) return \"enterprise\";\n if (t.includes(\"smb\")) return \"smb\";\n return \"mid-market\";\n}\n\n// Normalized output\nconst normalized = {\n quote_id: $('Quote Trigger (Webhook)').first().json.body.quoteId || null,\n opportunity_id: $('Fetch Opportunity Details').first().json.Id || null,\n account_id: $input.first().json.Id || null,\n\n // Core deal data\n deal_amount: $('Fetch Opportunity Details').first().json.Amount || 0,\n close_date: $('Fetch Opportunity Details').first().json.CloseDate || null,\n stage: $('Fetch Opportunity Details').first().json.StageName || \"unknown\",\n\n // Derived fields\n deal_size: getDealSize($('Fetch Opportunity Details').first().json.Amount),\n customer_segment: getCustomerSegment($input.first().json.Type),\n\n // Contextual enrichment\n industry: $input.first().json.Industry || \"unknown\",\n region: $input.first().json.BillingCity || \"unknown\", // optional future use\n\n // Metadata for AI\n timestamp: new Date().toISOString()\n};\n\nreturn [{ json: normalized }];\n"
},
"typeVersion": 2
},
{
"id": "3666ad30-7938-4067-8316-54dd3067a8c0",
"name": "Load Historical Deals (Sheets)",
"type": "n8n-nodes-base.googleSheets",
"position": [
1680,
704
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1pdRFz9s2_blZMAsf-4romcXUIOidqI6Kla3mMXZ0FRI",
"cachedResultUrl": "",
"cachedResultName": "HistoricalDeals"
}
},
"typeVersion": 4.7
},
{
"id": "94299de0-f2d4-4ef1-bd34-a9f7ef9d6fed",
"name": "Match Relevant Historical Deals",
"type": "n8n-nodes-base.code",
"position": [
1904,
704
],
"parameters": {
"jsCode": "const current = $items(\"Normalize Deal Context\")[0].json;\nconst history = items.map(item => item.json);\n\n// Normalize helper\nconst normalize = (val) => (val || \"\").toString().toLowerCase().trim();\n\nfunction score(deal) {\n let score = 0;\n if (normalize(deal.DealSize) === normalize(current.deal_size)) score += 3;\n if (normalize(deal.Segment) === normalize(current.customer_segment)) score += 2;\n if (normalize(deal.Industry) === normalize(current.industry)) score += 1;\n return score;\n}\n\nconst ranked = history\n .map(d => ({ ...d, score: score(d) }))\n .filter(d => d.score >= 3) // threshold\n .sort((a, b) => b.score - a.score);\n\nreturn ranked.map(d => ({ json: d }));"
},
"typeVersion": 2
},
{
"id": "1125e166-7a8d-4951-b684-eec2daf0ba36",
"name": "Compute Pricing Benchmarks",
"type": "n8n-nodes-base.code",
"position": [
2128,
704
],
"parameters": {
"jsCode": "const deals = items.map(item => item.json);\n\n// Separate won/lost deals\nconst wonDeals = deals.filter(d => (d.Outcome || \"\").toLowerCase() === \"won\");\nconst lostDeals = deals.filter(d => (d.Outcome || \"\").toLowerCase() === \"lost\");\n\n// Helper function\nconst avg = (arr, field) => {\n if (arr.length === 0) return 0;\n return arr.reduce((sum, d) => sum + Number(d[field] || 0), 0) / arr.length;\n};\n\n// Calculations\nconst avgWonDiscount = avg(wonDeals, \"DiscountGiven\");\nconst avgLostDiscount = avg(lostDeals, \"DiscountGiven\");\n\nconst winRate = deals.length > 0 ? (wonDeals.length / deals.length) : 0;\n\n// Safe pricing logic\nlet recommendedDiscount = avgWonDiscount;\n\n// Adjust if losing deals had higher discounts (bad sign)\nif (avgLostDiscount > avgWonDiscount) {\n recommendedDiscount = (avgWonDiscount + avgLostDiscount) / 2;\n}\n\n// Define safe range\nconst minDiscount = Math.max(0, avgWonDiscount - 2);\nconst maxDiscount = avgLostDiscount > 0 ? avgLostDiscount : avgWonDiscount + 5;\n\n// Output\nconst result = {\n total_deals_considered: deals.length,\n win_rate: Number(winRate.toFixed(2)),\n\n avg_won_discount: Number(avgWonDiscount.toFixed(2)),\n avg_lost_discount: Number(avgLostDiscount.toFixed(2)),\n\n recommended_discount: Number(recommendedDiscount.toFixed(2)),\n\n discount_range: {\n min: Number(minDiscount.toFixed(2)),\n max: Number(maxDiscount.toFixed(2))\n }\n};\n\nreturn [{ json: result }];"
},
"typeVersion": 2
},
{
"id": "45d6da6a-ddcb-41fc-a2a7-97fece11d474",
"name": "AI Pricing Strategist",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
2352,
704
],
"parameters": {
"text": "=Deal Context:\n- Deal Amount: {{ $('Match Relevant Historical Deals').item.json.FinalPrice }}\n- Deal Size:{{ $('Match Relevant Historical Deals').item.json.DealSize }} \n- Customer Segment: {{ $('Match Relevant Historical Deals').item.json.Segment }}\n- Industry: {{ $('Match Relevant Historical Deals').item.json.Industry }}\n\nHistorical Insights:\n- Total Deals Analyzed: {{$json[\"total_deals_considered\"]}}\n- Win Rate: {{$json[\"win_rate\"]}}\n- Avg Winning Discount: {{$json[\"avg_won_discount\"]}}%\n- Avg Losing Discount: {{$json[\"avg_lost_discount\"]}}%\n- Suggested Discount (Baseline): {{$json[\"recommended_discount\"]}}%\n- Safe Discount Range: {{$json[\"discount_range\"][\"min\"]}}% to {{$json[\"discount_range\"][\"max\"]}}%\n\nInstructions:\n1. Recommend an optimal discount percentage.\n2. Calculate the final price based on deal amount.\n3. Estimate win probability (0 to 1).\n4. Provide a strong justification using historical patterns and deal context.\n5. Mention if the deal is risky or safe.\n6. If data is weak, explicitly say confidence is low.\n\nOutput format:\n{\n \"recommended_discount\": number,\n \"final_price\": number,\n \"win_probability\": number,\n \"confidence\": \"high | medium | low\",\n \"risk_level\": \"low | medium | high\",\n \"justification\": \"detailed reasoning\"\n}",
"options": {
"systemMessage": "=You are a senior B2B pricing strategist with deep expertise in deal optimization, revenue growth, and competitive sales strategy.\n\nYour job is to recommend the optimal discount and pricing strategy for a deal using:\n- Historical pricing performance\n- Win/loss trends\n- Customer segment behavior\n- Deal size sensitivity\n- Competitive dynamics\n\nYou MUST follow these principles:\n\n1. Maximize win probability WITHOUT unnecessary discounting.\n2. Protect margins \u2014 avoid over-discounting unless strongly justified.\n3. Use historical data as the primary signal (not guesswork).\n4. If historical data shows higher discounts led to losses, AVOID increasing discounts.\n5. Be conservative for large deals unless strong justification exists.\n6. Provide reasoning like a human pricing expert, not a generic AI.\n\nOutput MUST be in strict JSON format.\n\nDO NOT include explanations outside JSON."
},
"promptType": "define"
},
"typeVersion": 3.1
},
{
"id": "6c01ccdc-c14a-4ba2-9b00-933b9ad044cf",
"name": "Structure AI Output",
"type": "n8n-nodes-base.set",
"position": [
2704,
704
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={{ $json.output }}"
},
"typeVersion": 3.4
},
{
"id": "4c79726f-235a-4ff9-8c6e-5cf5a1ee53f7",
"name": "Pre-Update Hook",
"type": "n8n-nodes-base.salesforce",
"position": [
2928,
704
],
"parameters": {
"resource": "account",
"operation": "__CUSTOM_API_CALL__"
},
"typeVersion": 1
},
{
"id": "8a37754b-ffc0-4df9-a0cb-35bb88e6c64c",
"name": "Update Quote in Salesforce",
"type": "n8n-nodes-base.httpRequest",
"position": [
3152,
704
],
"parameters": {
"url": "=https://{DOMAIN_NAME}/services/data/v59.0/sobjects/Quote/{{$node[\"Normalize Deal Context\"].json[\"quote_id\"]}}",
"method": "PATCH",
"options": {},
"jsonBody": "={\n \"Recommended_Discount__c\": {{ $('Structure AI Output').item.json.recommended_discount }},\n \"Final_Recommended_Price__c\": {{ $('Structure AI Output').item.json.final_price }},\n \"Win_Probability__c\": {{ $('Structure AI Output').item.json.win_probability }},\n \"Pricing_Confidence__c\": \"{{ $('Structure AI Output').item.json.confidence }}\",\n \"Deal_Risk_Level__c\": \"{{ $('Structure AI Output').item.json.risk_level }}\",\n \"Pricing_Justification__c\": \"{{ $('Structure AI Output').item.json.justification }}\"\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "salesforceOAuth2Api"
},
"typeVersion": 4.4
},
{
"id": "d39c1a78-1f8a-4145-a38c-414449995dbb",
"name": "Send Pricing Summary (Slack)",
"type": "n8n-nodes-base.slack",
"position": [
3376,
704
],
"parameters": {
"text": "=*AI Pricing Recommendation Applied*\n\n*Quote ID:* {{$node[\"Normalize Deal Context\"].json[\"quote_id\"]}}\n*Recommended Discount:* {{$node[\"Structure AI Output\"].json['recommended_discount']}}%\n*Final Price:* {{$node[\"Structure AI Output\"].json['final_price']}}\n*Win Probability:* {{$node[\"Structure AI Output\"].json['win_probability']}}\n\n*Risk Level:* {{$node[\"Structure AI Output\"].json['risk_level']}}\n*Confidence:* {{$node[\"Structure AI Output\"].json['confidence']}}\n\n*Justification*:\n{{$node[\"Structure AI Output\"].json['justification']}}",
"user": {
"__rl": true,
"mode": "list",
"value": "U0ANV4YLNTV",
"cachedResultName": ""
},
"select": "user",
"otherOptions": {
"includeLinkToWorkflow": false
},
"authentication": "oAuth2"
},
"typeVersion": 2.4
},
{
"id": "c5bf5411-bc48-4cc3-aa69-70d4a493cc07",
"name": "LLM Engine (Groq)",
"type": "@n8n/n8n-nodes-langchain.lmChatGroq",
"position": [
2432,
928
],
"parameters": {
"model": "openai/gpt-oss-120b",
"options": {}
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "d67fb04e-1d5f-49d9-843b-825da826a865",
"connections": {
"Pre-Update Hook": {
"main": [
[
{
"node": "Update Quote in Salesforce",
"type": "main",
"index": 0
}
]
]
},
"LLM Engine (Groq)": {
"ai_languageModel": [
[
{
"node": "AI Pricing Strategist",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Structure AI Output": {
"main": [
[
{
"node": "Pre-Update Hook",
"type": "main",
"index": 0
}
]
]
},
"AI Pricing Strategist": {
"main": [
[
{
"node": "Structure AI Output",
"type": "main",
"index": 0
}
]
]
},
"Fetch Account Details": {
"main": [
[
{
"node": "Normalize Deal Context",
"type": "main",
"index": 0
}
]
]
},
"Normalize Deal Context": {
"main": [
[
{
"node": "Load Historical Deals (Sheets)",
"type": "main",
"index": 0
}
]
]
},
"Quote Trigger (Webhook)": {
"main": [
[
{
"node": "Fetch Opportunity Details",
"type": "main",
"index": 0
}
]
]
},
"Fetch Opportunity Details": {
"main": [
[
{
"node": "Fetch Account Details",
"type": "main",
"index": 0
}
]
]
},
"Compute Pricing Benchmarks": {
"main": [
[
{
"node": "AI Pricing Strategist",
"type": "main",
"index": 0
}
]
]
},
"Update Quote in Salesforce": {
"main": [
[
{
"node": "Send Pricing Summary (Slack)",
"type": "main",
"index": 0
}
]
]
},
"Load Historical Deals (Sheets)": {
"main": [
[
{
"node": "Match Relevant Historical Deals",
"type": "main",
"index": 0
}
]
]
},
"Match Relevant Historical Deals": {
"main": [
[
{
"node": "Compute Pricing Benchmarks",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow receives Salesforce Quote events via a webhook, enriches them with Salesforce Opportunity and Account data, benchmarks the deal against historical outcomes stored in Google Sheets, uses Groq (LangChain agent) to generate a pricing recommendation, then updates the…
Source: https://n8n.io/workflows/17262/ — 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.
This n8n workflow orchestrates a powerful suite of AI Agents and automations to manage and optimize various aspects of an e-commerce operation, particularly for platforms like Shopify. It leverages La
Fully automates your service order pipeline from incoming booking to supplier confirmation — with built-in SLA enforcement and automatic escalation if a supplier goes silent. 📥 Receives orders via web
Know that feeling when a "low priority" ticket turns into a production fire? Or when your on-call rotation starts showing signs of serious burnout from alert overload?
This workflow receives a blog request via webhook, researches the topic with Tavily, generates a long-form HTML article using Google Gemini, creates two images via the kie.ai API, stores assets in Goo
This workflow automates customer feedback processing by analyzing sentiment, identifying key issues, generating personalized responses, and escalating critical cases to support teams when required. De