AutomationFlowsAI & RAG › Analyze Weekly Fireflies Sales Calls with Gpt-4o-mini, Google Sheets and Slack

Analyze Weekly Fireflies Sales Calls with Gpt-4o-mini, Google Sheets and Slack

ByisaWOW @isawow on n8n.io

Connect your Fireflies account once and activate the workflow — every Monday at 9AM it runs automatically without any input from you. It pulls all sales call transcripts from the past 7 days, analyzes each one with GPT-4o-mini, and extracts six intelligence fields: pricing…

Cron / scheduled trigger★★★★☆ complexityAI-powered21 nodesHTTP RequestAgentOpenAI ChatOutput Parser StructuredGoogle SheetsSlack
AI & RAG Trigger: Cron / scheduled Nodes: 21 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #15013 — 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 →

Download .json
{
  "nodes": [
    {
      "id": "8ee866e7-c499-4868-8e70-83d1e9e8a815",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2448,
        -240
      ],
      "parameters": {
        "width": 540,
        "height": 1140,
        "content": "## Weekly Sales Call Intelligence \u2014 Fireflies + GPT-4o-mini + Sheets + Slack\n\nFor sales managers and revenue teams who want automatic AI analysis of every sales call transcript every Monday morning. The workflow connects to your Fireflies account, fetches all transcripts from the past 7 days, and for each call uses GPT-4o-mini to extract six intelligence fields: pricing mentions, objections, buying signals, competitor mentions, key takeaway, and a recommended next action. Every call is logged as one row in Google Sheets. Slack receives a weekly aggregated report covering all calls, top objections, top buying signals, and competitor mentions.\n\n## How it works\n- **1. Schedule \u2014 Every Monday 9AM** triggers the workflow each week\n- **2. Set \u2014 Config Values** stores Fireflies API key, Sheet ID, Slack channel, and keywords\n- **3. HTTP \u2014 Fetch Recent Transcripts** pulls the 50 most recent transcripts from Fireflies\n- **4. Code \u2014 Filter Last 7 Days** filters to the past 7 days and outputs one item per transcript\n- **5. IF \u2014 Any Transcripts Found?** stops cleanly if no calls were recorded this week\n- **7. HTTP \u2014 Fetch Full Transcript** fetches complete transcript details for each call\n- **8. Code \u2014 Extract Transcript Data** extracts sentences, sentiment, keywords, and action items\n- **9. AI Agent \u2014 Analyze Sales Call** uses GPT-4o-mini to produce 6 structured intelligence fields\n- **12. Code \u2014 Combine Analysis Results** merges AI output with transcript metadata\n- **13. Google Sheets \u2014 Log Call Analysis** appends one row per call to the tracker sheet\n- **14. Code \u2014 Build Weekly Slack Summary** aggregates all calls into one weekly digest\n- **15. Slack \u2014 Send Weekly Report** delivers the weekly intelligence report to your channel\n\n## Set up steps\n1. In **2. Set \u2014 Config Values** \u2014 replace YOUR_FIREFLIES_API_KEY, YOUR_GOOGLE_SHEET_ID, sheet tab name, Slack channel, company name, and sales keywords\n2. In **10. OpenAI \u2014 GPT-4o-mini Model** \u2014 connect your OpenAI credential\n3. In **13. Google Sheets \u2014 Log Call Analysis** \u2014 connect your Google Sheets OAuth2 credential\n4. In **15. Slack \u2014 Send Weekly Report** \u2014 connect your Slack OAuth2 credential\n5. Create a Google Sheet tab named Sales Call Analysis with columns: Call Date, Meeting Title, Duration (min), Participants, Overall Sentiment, Pricing Mentions, Objections, Buying Signals, Competitor Mentions, Key Takeaway, Recommended Action, Transcript URL, Logged At\n6. Activate the workflow \u2014 it runs every Monday at 9AM automatically"
      },
      "typeVersion": 1
    },
    {
      "id": "382c29df-3cb0-4eef-9848-01a07636d098",
      "name": "Section \u2014 Schedule and Config",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1888,
        -48
      ],
      "parameters": {
        "color": 5,
        "width": 436,
        "height": 452,
        "content": "## Schedule and Config\nWorkflow triggers every Monday at 9AM. Config stores Fireflies API key, Sheet ID, Slack channel, company name, sales filter keywords, and the 7-day date window used throughout."
      },
      "typeVersion": 1
    },
    {
      "id": "1328aa41-8111-4195-84a2-f67436edf426",
      "name": "Section \u2014 Transcript Fetch, Filter, and Gate",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1424,
        -48
      ],
      "parameters": {
        "color": 6,
        "width": 612,
        "height": 756,
        "content": "## Transcript Fetch, Filter, and Gate\nFetches the 50 most recent Fireflies transcripts then filters to the past 7 days. Outputs one item per transcript. The IF node checks if any calls exist \u2014 no calls this week exits cleanly via the Set node below."
      },
      "typeVersion": 1
    },
    {
      "id": "9bab136a-fd82-443b-9b88-37b2d0f56b93",
      "name": "Section \u2014 Full Transcript Fetch and AI Analysis",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -720,
        -48
      ],
      "parameters": {
        "color": 6,
        "width": 836,
        "height": 852,
        "content": "## Full Transcript Fetch and AI Analysis\nFor each transcript, fetches complete details including sentences, ai_filters (pricing, questions, tasks), summary, and sentiment analytics. GPT-4o-mini produces 6 structured intelligence fields per call via Structured Output Parser."
      },
      "typeVersion": 1
    },
    {
      "id": "a1188f3a-8c16-487d-a743-1e5fff3f80aa",
      "name": "Section \u2014 Results Assembly and Output",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        -48
      ],
      "parameters": {
        "color": 4,
        "width": 660,
        "height": 852,
        "content": "## Results Assembly and Output\nMerges AI output with metadata. Google Sheets logs one row per call. Code node aggregates all calls into a weekly digest covering objections, buying signals, and competitors. Slack delivers the report."
      },
      "typeVersion": 1
    },
    {
      "id": "0e2b31bb-4dc9-4f1a-a2c4-76950f8100bc",
      "name": "Note \u2014 Edit Config Before Activating",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1584,
        848
      ],
      "parameters": {
        "color": 3,
        "width": 892,
        "content": "## \u26a0\ufe0f Edit This Node Before Activating\nReplace all six values: Fireflies API key (from fireflies.ai Settings then Integrations), Google Sheet ID, sheet tab name, Slack channel, company name, and comma-separated sales keywords used to identify relevant calls."
      },
      "typeVersion": 1
    },
    {
      "id": "f5b5751c-2d3b-41cd-a6d0-4c08329f936b",
      "name": "1. Schedule \u2014 Every Monday 9AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1840,
        224
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * 1"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ab84aac9-cdae-4a90-8690-5611b4026c9c",
      "name": "2. Set \u2014 Config Values",
      "type": "n8n-nodes-base.set",
      "position": [
        -1616,
        224
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-001",
              "name": "firefliesApiKey",
              "type": "string",
              "value": "YOUR_FIREFLIES_API_KEY"
            },
            {
              "id": "cfg-002",
              "name": "sheetId",
              "type": "string",
              "value": "YOUR_GOOGLE_SHEET_ID"
            },
            {
              "id": "cfg-003",
              "name": "sheetName",
              "type": "string",
              "value": "Sales Call Analysis"
            },
            {
              "id": "cfg-004",
              "name": "slackChannel",
              "type": "string",
              "value": "#sales-team"
            },
            {
              "id": "cfg-005",
              "name": "companyName",
              "type": "string",
              "value": "YOUR COMPANY NAME"
            },
            {
              "id": "cfg-006",
              "name": "salesKeywords",
              "type": "string",
              "value": "sales,client,demo,proposal,pricing,onboarding,deal,contract"
            },
            {
              "id": "cfg-007",
              "name": "weekStart",
              "type": "string",
              "value": "={{ $now.minus({days: 7}).toFormat('dd MMM yyyy') }}"
            },
            {
              "id": "cfg-008",
              "name": "weekEnd",
              "type": "string",
              "value": "={{ $now.toFormat('dd MMM yyyy') }}"
            },
            {
              "id": "cfg-009",
              "name": "sevenDaysAgoMs",
              "type": "number",
              "value": "={{ $now.minus({days: 7}).toMillis() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "fad8ef6e-3d7e-49f9-a792-d27c507bf31c",
      "name": "3. HTTP \u2014 Fetch Recent Transcripts",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1392,
        224
      ],
      "parameters": {
        "url": "https://api.fireflies.ai/graphql",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"query\": \"query GetRecentTranscripts { transcripts(limit: 50) { id title date duration participants } }\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Authorization",
              "value": "=Bearer {{ $json.firefliesApiKey }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "65ad4e9b-2f9f-4a9b-92f5-6c4a7c95973c",
      "name": "4. Code \u2014 Filter Last 7 Days",
      "type": "n8n-nodes-base.code",
      "position": [
        -1168,
        224
      ],
      "parameters": {
        "jsCode": "// Filter transcripts from last 7 days that match sales keywords\nconst response = $input.first().json;\nconst config = $('2. Set \u2014 Config Values').item.json;\n\n// Extract transcripts array from GraphQL response\nconst transcripts = response.data?.transcripts || [];\n\nif (transcripts.length === 0) {\n  return [{\n    json: {\n      hasTranscripts: false,\n      message: 'No transcripts found in Fireflies account.',\n      weekStart: config.weekStart,\n      weekEnd: config.weekEnd,\n      slackChannel: config.slackChannel,\n      companyName: config.companyName\n    }\n  }];\n}\n\n// Filter to last 7 days\nconst sevenDaysAgo = config.sevenDaysAgoMs;\nconst keywords = config.salesKeywords.toLowerCase().split(',').map(k => k.trim());\n\nconst recentSalesCalls = transcripts.filter(t => {\n  const transcriptDate = t.date || 0;\n  return transcriptDate >= sevenDaysAgo;\n});\n\nif (recentSalesCalls.length === 0) {\n  return [{\n    json: {\n      hasTranscripts: false,\n      message: `No transcripts found in the last 7 days (${config.weekStart} to ${config.weekEnd}).`,\n      weekStart: config.weekStart,\n      weekEnd: config.weekEnd,\n      slackChannel: config.slackChannel,\n      companyName: config.companyName\n    }\n  }];\n}\n\n// Return one item per transcript for the loop\nreturn recentSalesCalls.map(t => ({\n  json: {\n    hasTranscripts: true,\n    transcriptId: t.id,\n    transcriptTitle: t.title || 'Untitled Meeting',\n    transcriptDate: t.date\n      ? new Date(t.date).toISOString().split('T')[0]\n      : 'Unknown Date',\n    durationMinutes: Math.round((t.duration || 0) / 60),\n    participants: (t.participants || []).join(', ') || 'Unknown',\n    firefliesApiKey: config.firefliesApiKey,\n    sheetId: config.sheetId,\n    sheetName: config.sheetName,\n    slackChannel: config.slackChannel,\n    companyName: config.companyName,\n    weekStart: config.weekStart,\n    weekEnd: config.weekEnd,\n    totalCallsThisWeek: recentSalesCalls.length\n  }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "57c4228d-5638-403f-b160-0c73913297b1",
      "name": "5. IF \u2014 Any Transcripts Found?",
      "type": "n8n-nodes-base.if",
      "position": [
        -960,
        224
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-has-transcripts",
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.hasTranscripts }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "da124254-5cb9-473f-826d-237b29d83d72",
      "name": "6. Set \u2014 No Calls This Week",
      "type": "n8n-nodes-base.set",
      "position": [
        -960,
        432
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "noop-001",
              "name": "result",
              "type": "string",
              "value": "=No sales calls found this week. Nothing to analyze."
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "97e93b4b-7b7e-4e23-9740-c59dbdb63abd",
      "name": "7. HTTP \u2014 Fetch Full Transcript",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -688,
        208
      ],
      "parameters": {
        "url": "https://api.fireflies.ai/graphql",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"query\": \"query GetTranscriptDetails($id: String!) { transcript(id: $id) { id title date duration participants transcript_url sentences { speaker_name text ai_filters { task pricing metric question date_and_time sentiment } } summary { keywords action_items overview } analytics { sentiments { positive_pct neutral_pct negative_pct } } } }\",\n  \"variables\": {\n    \"id\": \"{{ $json.transcriptId }}\"\n  }\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Authorization",
              "value": "=Bearer {{ $json.firefliesApiKey }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "dd1c274e-b3f8-4125-b98d-57d1b64dcf7f",
      "name": "8. Code \u2014 Extract Transcript Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -464,
        208
      ],
      "parameters": {
        "jsCode": "// Extract and prepare transcript data for AI analysis\nconst response = $input.first().json;\nconst prevData = $('4. Code \u2014 Filter Last 7 Days').item.json;\n\n// Extract transcript from GraphQL response\nconst transcript = response.data?.transcript || {};\n\n// Build full text from sentences \u2014 limit to 4000 chars for GPT\nconst sentences = transcript.sentences || [];\nlet fullText = '';\nlet pricingSentences = [];\nlet questionSentences = [];\nlet taskSentences = [];\n\nsentences.forEach(s => {\n  const speaker = s.speaker_name || 'Unknown';\n  const text = s.text || '';\n  fullText += `${speaker}: ${text}\\n`;\n\n  if (s.ai_filters?.pricing) pricingSentences.push(`${speaker}: ${text}`);\n  if (s.ai_filters?.question) questionSentences.push(`${speaker}: ${text}`);\n  if (s.ai_filters?.task) taskSentences.push(`${speaker}: ${text}`);\n});\n\nconst truncatedText = fullText.substring(0, 4000);\n\nconst summary = transcript.summary || {};\nconst keywords = (summary.keywords || []).slice(0, 10).join(', ');\nconst actionItems = (summary.action_items || []).slice(0, 5).join(' | ');\nconst overview = summary.overview || 'No overview available';\n\nconst sentiments = transcript.analytics?.sentiments || {};\nconst positivePct = Math.round(sentiments.positive_pct || 0);\nconst neutralPct = Math.round(sentiments.neutral_pct || 0);\nconst negativePct = Math.round(sentiments.negative_pct || 0);\n\nlet overallSentiment = 'Neutral';\nif (positivePct > 60) overallSentiment = 'Positive';\nelse if (negativePct > 40) overallSentiment = 'Negative';\nelse if (positivePct > negativePct) overallSentiment = 'Mostly Positive';\nelse overallSentiment = 'Mixed';\n\nreturn [{\n  json: {\n    transcriptId: transcript.id || prevData.transcriptId,\n    transcriptTitle: transcript.title || prevData.transcriptTitle,\n    transcriptDate: prevData.transcriptDate,\n    durationMinutes: Math.round((transcript.duration || 0) / 60) || prevData.durationMinutes,\n    participants: (transcript.participants || []).join(', ') || prevData.participants,\n    transcriptUrl: transcript.transcript_url || 'Not available',\n    truncatedText,\n    pricingSentences: pricingSentences.slice(0, 5).join(' | ') || 'None detected',\n    questionSentences: questionSentences.slice(0, 5).join(' | ') || 'None detected',\n    taskSentences: taskSentences.slice(0, 5).join(' | ') || 'None detected',\n    keywords,\n    actionItems,\n    overview,\n    overallSentiment,\n    positivePct,\n    negativePct,\n    firefliesApiKey: prevData.firefliesApiKey,\n    sheetId: prevData.sheetId,\n    sheetName: prevData.sheetName,\n    slackChannel: prevData.slackChannel,\n    companyName: prevData.companyName,\n    weekStart: prevData.weekStart,\n    weekEnd: prevData.weekEnd,\n    totalCallsThisWeek: prevData.totalCallsThisWeek\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "c2d49ee9-0a04-4ede-a49f-31c01e6e4459",
      "name": "9. AI Agent \u2014 Analyze Sales Call",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -240,
        208
      ],
      "parameters": {
        "text": "=You are a sales intelligence analyst at {{ $json.companyName }}.\n\nAnalyze this sales call transcript and extract structured intelligence.\n\nCALL DETAILS:\nTitle: {{ $json.transcriptTitle }}\nDate: {{ $json.transcriptDate }}\nDuration: {{ $json.durationMinutes }} minutes\nParticipants: {{ $json.participants }}\nOverall Sentiment: {{ $json.overallSentiment }} (Positive: {{ $json.positivePct }}%, Negative: {{ $json.negativePct }}%)\n\nFIREFLIES AI-DETECTED PRICING SENTENCES:\n{{ $json.pricingSentences }}\n\nFIREFLIES AI-DETECTED QUESTIONS:\n{{ $json.questionSentences }}\n\nFIREFLIES KEYWORDS: {{ $json.keywords }}\n\nFIREFLIES OVERVIEW: {{ $json.overview }}\n\nTRANSCRIPT EXCERPT:\n{{ $json.truncatedText }}\n\nReturn ONLY a valid JSON object with exactly these 6 fields. No extra text. No markdown. No backticks.\n\npricingMentions \u2014 List the specific prices, packages, budgets, or cost discussions mentioned. If none, write: No pricing discussed. Keep under 80 words.\n\nobjections \u2014 List every objection or concern raised by the prospect or client. Each objection on a new line starting with a dash. If none found, write: No objections detected.\n\nbuyingSignals \u2014 List every positive signal showing the prospect is interested or moving toward a decision. Examples: asked about timeline, requested proposal, mentioned budget availability. If none, write: No buying signals detected.\n\ncompetitorMentions \u2014 List any competitor names or alternative products mentioned. If none, write: No competitors mentioned.\n\nkeyTakeaway \u2014 One clear sentence summarizing what happened in this call and what the next step should be. Under 25 words.\n\nrecommendedAction \u2014 One specific action the sales rep should take within 48 hours based on this call. Be concrete and direct. Under 20 words.",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.7
    },
    {
      "id": "48d48105-3f0b-49f4-b723-ba4468036b06",
      "name": "10. OpenAI \u2014 GPT-4o-mini Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -240,
        416
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {
          "maxTokens": 800,
          "temperature": 0.3
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "5d09b2aa-97c4-42be-9425-24cbce6c3abd",
      "name": "11. Parser \u2014 Structured Call Analysis",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -96,
        624
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"pricingMentions\": {\n      \"type\": \"string\",\n      \"description\": \"Specific prices, packages, budgets discussed in the call\"\n    },\n    \"objections\": {\n      \"type\": \"string\",\n      \"description\": \"Objections and concerns raised by the prospect, one per line starting with dash\"\n    },\n    \"buyingSignals\": {\n      \"type\": \"string\",\n      \"description\": \"Positive signals showing interest or movement toward a decision\"\n    },\n    \"competitorMentions\": {\n      \"type\": \"string\",\n      \"description\": \"Competitor names or alternative products mentioned\"\n    },\n    \"keyTakeaway\": {\n      \"type\": \"string\",\n      \"description\": \"One sentence summary of what happened and next step. Under 25 words.\"\n    },\n    \"recommendedAction\": {\n      \"type\": \"string\",\n      \"description\": \"One specific action sales rep should take within 48 hours. Under 20 words.\"\n    }\n  },\n  \"required\": [\"pricingMentions\", \"objections\", \"buyingSignals\", \"competitorMentions\", \"keyTakeaway\", \"recommendedAction\"]\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "18669f4a-cfae-4653-854d-1a12e048661b",
      "name": "12. Code \u2014 Combine Analysis Results",
      "type": "n8n-nodes-base.code",
      "position": [
        272,
        208
      ],
      "parameters": {
        "jsCode": "// Combine AI analysis output with transcript metadata\nconst aiOutput = $input.first().json.output;\nconst transcriptData = $('8. Code \u2014 Extract Transcript Data').item.json;\n\nreturn [{\n  json: {\n    callDate: transcriptData.transcriptDate,\n    callTitle: transcriptData.transcriptTitle,\n    durationMinutes: transcriptData.durationMinutes,\n    participants: transcriptData.participants,\n    overallSentiment: transcriptData.overallSentiment,\n    transcriptUrl: transcriptData.transcriptUrl,\n    pricingMentions: aiOutput.pricingMentions || 'No pricing discussed',\n    objections: aiOutput.objections || 'No objections detected',\n    buyingSignals: aiOutput.buyingSignals || 'No buying signals detected',\n    competitorMentions: aiOutput.competitorMentions || 'No competitors mentioned',\n    keyTakeaway: aiOutput.keyTakeaway || 'No takeaway generated',\n    recommendedAction: aiOutput.recommendedAction || 'No action recommended',\n    sheetId: transcriptData.sheetId,\n    sheetName: transcriptData.sheetName,\n    slackChannel: transcriptData.slackChannel,\n    companyName: transcriptData.companyName,\n    weekStart: transcriptData.weekStart,\n    weekEnd: transcriptData.weekEnd,\n    totalCallsThisWeek: transcriptData.totalCallsThisWeek,\n    loggedAt: new Date().toISOString().replace('T', ' ').substring(0, 16)\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "d0fd31a0-e4f5-4f7a-8fb1-298d43165082",
      "name": "13. Google Sheets \u2014 Log Call Analysis",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        496,
        64
      ],
      "parameters": {
        "columns": {
          "value": {
            "Call Date": "={{ $json.callDate }}",
            "Logged At": "={{ $json.loggedAt }}",
            "Objections": "={{ $json.objections }}",
            "Key Takeaway": "={{ $json.keyTakeaway }}",
            "Participants": "={{ $json.participants }}",
            "Meeting Title": "={{ $json.callTitle }}",
            "Buying Signals": "={{ $json.buyingSignals }}",
            "Duration (min)": "={{ $json.durationMinutes }}",
            "Transcript URL": "={{ $json.transcriptUrl }}",
            "Pricing Mentions": "={{ $json.pricingMentions }}",
            "Overall Sentiment": "={{ $json.overallSentiment }}",
            "Recommended Action": "={{ $json.recommendedAction }}",
            "Competitor Mentions": "={{ $json.competitorMentions }}"
          },
          "mappingMode": "defineBelow"
        },
        "options": {
          "cellFormat": "USER_ENTERED"
        },
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.sheetName }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.sheetId }}"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "2ac71792-f76e-42e7-ba82-9125b39efd79",
      "name": "14. Code \u2014 Build Weekly Slack Summary",
      "type": "n8n-nodes-base.code",
      "position": [
        496,
        336
      ],
      "parameters": {
        "jsCode": "// Aggregate all analyzed calls into weekly summary for Slack\nconst allItems = $input.all();\n\nif (!allItems || allItems.length === 0) {\n  return [{\n    json: {\n      slackMessage: 'No sales calls analyzed this week.',\n      slackChannel: '#sales-team'\n    }\n  }];\n}\n\nconst config = allItems[0].json;\nconst totalCalls = allItems.length;\n\nconst allObjections = [];\nconst allBuyingSignals = [];\nconst allCompetitors = [];\nconst callSummaries = [];\nlet positiveCallCount = 0;\nlet negativeCallCount = 0;\n\nallItems.forEach(item => {\n  const d = item.json;\n\n  if (d.overallSentiment === 'Positive' || d.overallSentiment === 'Mostly Positive') positiveCallCount++;\n  if (d.overallSentiment === 'Negative') negativeCallCount++;\n\n  if (d.objections && !d.objections.toLowerCase().includes('no objection')) {\n    allObjections.push(`[${d.callTitle}]: ${d.objections.substring(0, 100)}`);\n  }\n\n  if (d.buyingSignals && !d.buyingSignals.toLowerCase().includes('no buying')) {\n    allBuyingSignals.push(`[${d.callTitle}]: ${d.buyingSignals.substring(0, 100)}`);\n  }\n\n  if (d.competitorMentions && !d.competitorMentions.toLowerCase().includes('no competitor')) {\n    allCompetitors.push(d.competitorMentions.substring(0, 60));\n  }\n\n  callSummaries.push(`${d.callDate} | ${d.callTitle} | ${d.durationMinutes}min | ${d.overallSentiment} | ${d.keyTakeaway}`);\n});\n\nconst uniqueCompetitors = [...new Set(allCompetitors)].join(', ') || 'None mentioned';\n\nconst slackMessage = `*Weekly Sales Call Intelligence Report*\n*${config.companyName} | ${config.weekStart} to ${config.weekEnd}*\n\n*SUMMARY*\nTotal Calls Analyzed: ${totalCalls}\nPositive Calls: ${positiveCallCount}\nCalls with Objections: ${allObjections.length}\nCalls with Buying Signals: ${allBuyingSignals.length}\nCompetitors Mentioned: ${uniqueCompetitors}\n\n*TOP OBJECTIONS THIS WEEK*\n${allObjections.slice(0, 3).join('\\n') || 'No objections recorded this week'}\n\n*TOP BUYING SIGNALS*\n${allBuyingSignals.slice(0, 3).join('\\n') || 'No buying signals recorded this week'}\n\n*CALL BY CALL OVERVIEW*\n${callSummaries.join('\\n')}\n\n_Full analysis logged to Google Sheets_`;\n\nreturn [{\n  json: {\n    slackMessage,\n    slackChannel: config.slackChannel\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "4166a1ec-7058-4e53-af36-c52268ce377d",
      "name": "15. Slack \u2014 Send Weekly Report",
      "type": "n8n-nodes-base.slack",
      "position": [
        720,
        336
      ],
      "parameters": {
        "text": "={{ $json.slackMessage }}",
        "otherOptions": {
          "mrkdwn": true
        },
        "authentication": "oAuth2"
      },
      "typeVersion": 2.2
    }
  ],
  "connections": {
    "2. Set \u2014 Config Values": {
      "main": [
        [
          {
            "node": "3. HTTP \u2014 Fetch Recent Transcripts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4. Code \u2014 Filter Last 7 Days": {
      "main": [
        [
          {
            "node": "5. IF \u2014 Any Transcripts Found?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1. Schedule \u2014 Every Monday 9AM": {
      "main": [
        [
          {
            "node": "2. Set \u2014 Config Values",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "10. OpenAI \u2014 GPT-4o-mini Model": {
      "ai_languageModel": [
        [
          {
            "node": "9. AI Agent \u2014 Analyze Sales Call",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "5. IF \u2014 Any Transcripts Found?": {
      "main": [
        [
          {
            "node": "7. HTTP \u2014 Fetch Full Transcript",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "6. Set \u2014 No Calls This Week",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7. HTTP \u2014 Fetch Full Transcript": {
      "main": [
        [
          {
            "node": "8. Code \u2014 Extract Transcript Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9. AI Agent \u2014 Analyze Sales Call": {
      "main": [
        [
          {
            "node": "12. Code \u2014 Combine Analysis Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8. Code \u2014 Extract Transcript Data": {
      "main": [
        [
          {
            "node": "9. AI Agent \u2014 Analyze Sales Call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3. HTTP \u2014 Fetch Recent Transcripts": {
      "main": [
        [
          {
            "node": "4. Code \u2014 Filter Last 7 Days",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "12. Code \u2014 Combine Analysis Results": {
      "main": [
        [
          {
            "node": "13. Google Sheets \u2014 Log Call Analysis",
            "type": "main",
            "index": 0
          },
          {
            "node": "14. Code \u2014 Build Weekly Slack Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "11. Parser \u2014 Structured Call Analysis": {
      "ai_outputParser": [
        [
          {
            "node": "9. AI Agent \u2014 Analyze Sales Call",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "14. Code \u2014 Build Weekly Slack Summary": {
      "main": [
        [
          {
            "node": "15. Slack \u2014 Send Weekly Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Connect your Fireflies account once and activate the workflow — every Monday at 9AM it runs automatically without any input from you. It pulls all sales call transcripts from the past 7 days, analyzes each one with GPT-4o-mini, and extracts six intelligence fields: pricing…

Source: https://n8n.io/workflows/15013/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Created by: Peyton Leveillee Last updated: October 2025

OpenAI Chat, Google Sheets, HTTP Request +5
AI & RAG

This workflow automates end-to-end ESG (Environmental, Social, and Governance) sustainability reporting for enterprise sustainability teams, compliance officers, and green governance leads. It solves

Agent, OpenAI Chat, Output Parser Structured +12
AI & RAG

Automates sales data analysis and strategic insight generation for sales managers and strategists needing actionable intelligence. Fetches multi-source data from sales, marketing, and financial system

HTTP Request, Agent, OpenAI Chat +6
AI & RAG

Scheduled triggers run automated price checks across multiple travel data sources. The collected data is aggregated, validated, and processed through an AI analysis layer that compares trends, detects

HTTP Request, OpenAI Chat, Agent +4
AI & RAG

This workflow automates comprehensive risk signal detection and regulatory compliance management across financial and claims data sources. Designed for risk management teams, compliance officers, and

HTTP Request, Agent, OpenAI Chat +5