{
  "id": "8Kz1ZPYp6wryQG3C",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "[INTERN - Aaron] Audio analysis & Potential customer Template (3)",
  "tags": [],
  "nodes": [
    {
      "id": "0d9787d8-e9ed-47d9-aefe-1722a338db0d",
      "name": "TriggerGDriveFolderChange",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "position": [
        -544,
        320
      ],
      "parameters": {
        "event": "fileCreated",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "mode": "list",
          "value": "1fhX3dpu9RNh0K5NkNJ_ysRBQhQJIGk8c",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1fhX3dpu9RNh0K5NkNJ_ysRBQhQJIGk8c",
          "cachedResultName": "[TMPLT-3] Call Recordings"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "79be87ad-f8db-4176-b81f-5b46656daeca",
      "name": "No Operation, do nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -160,
        400
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "afddb095-8948-4084-84a4-a15274a4cd9c",
      "name": "Analyze audio",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        368,
        336
      ],
      "parameters": {
        "text": "=You are an expert Sales Quality Assurance and Lead Scoring AI Agent. Your task is to analyze a sales call audio recording between a Sales Representative and a Customer/Prospect, then extract key business metrics and context.\n\nAnalyze the provided audio and output ONLY a valid JSON object matching the schema below. Do not include any introductory or concluding text.\n\n### ANALYSIS RULES:\n1. \"sentiment\": Must be \"Positive\", \"Neutral\", or \"Negative\".\n2. \"sentiment_score\": A float value between -1.0 (extremely negative) and 1.0 (extremely positive).\n3. \"lead_qualification\": Categorize as:\n   - \"Hot Lead\": Showed high intent to buy, accepted an offer, or ready for next steps.\n   - \"Warm Lead\": Showed interest but has objections (price, timing, needs info) that need addressing.\n   - \"Cold Lead\": Expressed clear rejection, no budget, locked in competitor contracts, or requested no contact.\n4. \"objection_category\": Identify the main objection/pain point (e.g., \"Pricing/Budget\", \"Competitor Contract\", \"Security/Compliance\", \"Feature Comparison\", \"None\").\n5. \"summary\": A concise 1-2 sentence summary of the conversation context.\n6. \"recommended_action\": A clear, actionable next step for the sales team.\n7. \"follow_up_status\": Set as \"Assigned to Sales\", \"Nurturing\", \"Closed / Unqualified\", or \"Do Not Call\".\n\n### OUTPUT JSON FORMAT:\n{\n  \"prospect_name\": \"Extract if mentioned, else 'Unknown'\",\n  \"company_name\": \"Extract if mentioned, else 'Unknown'\",\n  \"summary\": \"String\",\n  \"sentiment\": \"Positive / Neutral / Negative\",\n  \"sentiment_score\": 0.00,\n  \"objection_category\": \"String\",\n  \"lead_qualification\": \"Hot Lead / Warm Lead / Cold Lead\",\n  \"recommended_action\": \"String\",\n  \"follow_up_status\": \"String\"\n}",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-3.6-flash",
          "cachedResultName": "models/gemini-3.6-flash"
        },
        "options": {},
        "resource": "audio",
        "inputType": "binary",
        "operation": "analyze"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1.2
    },
    {
      "id": "dc5d61db-06f5-43db-a20d-278ad1adf5ad",
      "name": "SplitBatch",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        112,
        320
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "e6e5fd98-f797-40e0-a316-291dd9ee4212",
      "name": "Wait30Sec",
      "type": "n8n-nodes-base.wait",
      "position": [
        1040,
        336
      ],
      "parameters": {
        "amount": 30
      },
      "typeVersion": 1.1
    },
    {
      "id": "7b928e65-53de-44b7-b49f-eca24603c953",
      "name": "IsAudioCheck",
      "type": "n8n-nodes-base.if",
      "position": [
        -320,
        320
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "430c144e-4b52-42f4-9916-6aa4d143b951",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.mimeType }}",
              "rightValue": "audio"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "72b72d25-d40c-4fbb-bbd5-9b448b10c477",
      "name": "DownloadFileUploaded",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -160,
        208
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "8eec790e-8bce-43c3-9862-92ebfc5ba647",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        48
      ],
      "parameters": {
        "width": 224,
        "height": 480,
        "content": "# Google Drive Folder Trigger\nMonitors a specific Google Drive folder every minute for newly created files."
      },
      "typeVersion": 1
    },
    {
      "id": "1732fd4b-b9f0-4c88-982e-76b2dc8d63d8",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -336,
        48
      ],
      "parameters": {
        "width": 336,
        "height": 480,
        "content": "# Check File Type & Download\n1. Evaluates whether the uploaded file's mimeType contains \"audio\".\n2. Downloads the binary content of the verified audio file using the file ID from Google Drive."
      },
      "typeVersion": 1
    },
    {
      "id": "2ea01065-a3fe-4085-ba3b-0c70306cf607",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        32,
        48
      ],
      "parameters": {
        "width": 256,
        "height": 480,
        "content": "# Split File Downloaded into batch\nIterates through incoming files individually to prevent API rate limit issues during model execution."
      },
      "typeVersion": 1
    },
    {
      "id": "0b66c23c-fe3d-47ca-b7ac-f8de90b0e79d",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        48
      ],
      "parameters": {
        "width": 864,
        "height": 480,
        "content": "# Analyze Audio, Save Info and Wait 30 Seconds\n1. Analyze Audio with Gemini: Uses models/gemini-3.6-flash to analyze the audio binary directly. Evaluates sentiment, sentiment score, lead qualification, objection category, conversation summary, and recommended sales action.\n2. Parse Analysis Output: Extracts and structures the raw JSON response received from the Gemini analysis into individual, clean data variables.\n3. Save to Spreadsheet: Map and append the extracted attributes (such as Lead Qualification, Sentiment Score, Objection Category, and Recommended Action) into the corresponding columns of the target Google Sheet.\n4. Rate Limit Delay: Introduces a 30-second delay between processing batches to adhere to model rate limits."
      },
      "typeVersion": 1
    },
    {
      "id": "bab5babb-4995-41be-9173-c99a576f0c98",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        -400
      ],
      "parameters": {
        "color": 5,
        "width": 544,
        "height": 1344,
        "content": "# Sales Audio Call Analysis & Lead Scoring Pipeline\n\nThis workflow automates the end-to-end processing of sales call recordings uploaded to Google Drive. It extracts key business metrics, such as caller sentiment, objections, lead qualifications, and recommended follow-up actions, using Google Gemini, and directly appends the structured outputs into a Google Sheet.\n\nTo ensure seamless integration with the workflow, please make a copy of the following Google Sheets template for your database setup:\n\n\ud83d\udd17 Spreadsheet Template: [Spreadsheet_Sentiment Template](https://docs.google.com/spreadsheets/d/1H-ZEYGJXuOMRIz4WgU6zlhiR_dC-ZxxgSxMW5JBjIuM/edit?usp=sharing)\n\n---\n\n## Who\u2019s it for?\nFor sales teams, account executives, quality assurance managers, and revenue operations specialists who want to automate lead qualification, sales call analysis, and CRM/spreadsheet logging directly from raw audio recordings.\n\n---\n\n## How it works\n1. **Trigger:** Listens for new call recording files uploaded to a designated Google Drive folder.\n2. **Validation & Download:** Checks if the uploaded file is an audio file. Non-audio files are ignored via a No-Op node, while valid audio files are downloaded into binary format.\n3. **Batching:** Splits incoming files into individual items (`SplitBatch`) to process audio sequentially and prevent rate-limiting issues.\n4. **Audio Analysis:** Google Gemini (`gemini-3.6-flash`) processes the audio binary directly to perform speech-to-intent analysis, evaluating sentiment, sentiment score, lead qualification status, objection categories, summary, and recommended actions.\n5. **JSON Parsing:** A Set node (`ParseJsonOutput`) extracts and structures the raw JSON response returned by Gemini into individual fields.\n6. **Data Entry & Integration:** The standard Google Sheets node (`SaveInfo`) maps and appends the extracted structured data into the destination spreadsheet (`Call Sheet`).\n7. **Rate Limit Delay:** A 30-second delay (`Wait30Sec`) is triggered after saving to respect API rate limits before loop-processing the next batch item.\n\n---\n\n## How to set up\n- **Google Drive Setup:** Connect your Google Drive OAuth2 credentials in `TriggerGDriveFolderChange` and select the target folder where call recordings are uploaded.\n- **Google Gemini Credentials:** Add your Google Gemini API credentials to the `Analyze audio` node.\n- **Google Sheets Setup:** Connect your Google Sheets OAuth2 credentials to the `SaveInfo` node, select your target document (`Spreadsheet_Sentiment`), and specify the target sheet tab (`Call Sheet` or `gid=0`).\n- **Activate Workflow:** Toggle the workflow to **Active** to process new audio recordings in real time."
      },
      "typeVersion": 1
    },
    {
      "id": "e35f9c88-f36b-4128-ba84-63634aeee22d",
      "name": "SaveInfo",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        816,
        336
      ],
      "parameters": {
        "columns": {
          "value": {
            "No": "-",
            "Call ID": "-",
            "Sentiment": "={{ $json.sentiment }}",
            "Timestamp": "={{ $now.format('yyyy-MM-dd, HH:mm') }}",
            "Company Name": "={{ $json.company_name }}",
            "Phone Number": "-",
            "Prospect Name": "={{ $json.prospect_name }}",
            "Follow-up Status": "={{ $json.follow_up_status }}",
            "Lead Qualification": "={{ $json.lead_qualification }}",
            "Objection Category": "={{ $json.objection_category }}",
            "Recommended Action": "={{ $json.recommended_action }}",
            "Conversation Summary": "={{ $json.summary }}",
            "Sentiment Score (-1 to 1)": "={{ $json.sentiment_score }}"
          },
          "schema": [
            {
              "id": "No",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "No",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Call ID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Call ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Prospect Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Prospect Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Company Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Company Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Phone Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Conversation Summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Conversation Summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Sentiment",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Sentiment",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Sentiment Score (-1 to 1)",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Sentiment Score (-1 to 1)",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Objection Category",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Objection Category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Lead Qualification",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Lead Qualification",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Recommended Action",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Recommended Action",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Follow-up Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Follow-up Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "useAppend": false
        },
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1H-ZEYGJXuOMRIz4WgU6zlhiR_dC-ZxxgSxMW5JBjIuM/edit#gid=0",
          "cachedResultName": "Call Sheet"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1H-ZEYGJXuOMRIz4WgU6zlhiR_dC-ZxxgSxMW5JBjIuM",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1H-ZEYGJXuOMRIz4WgU6zlhiR_dC-ZxxgSxMW5JBjIuM/edit?usp=drivesdk",
          "cachedResultName": "Spreadsheet_Sentiment"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "2478abab-fc4c-4056-a8b9-4b07b9fbc0a6",
      "name": "ParseJsonOutput",
      "type": "n8n-nodes-base.set",
      "position": [
        592,
        336
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={{ $json.content.parts[0].text }}"
      },
      "typeVersion": 3.5
    }
  ],
  "active": true,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "2ec06e26-0217-4191-9d97-06bc0a27c06a",
  "nodeGroups": [],
  "connections": {
    "SaveInfo": {
      "main": [
        [
          {
            "node": "Wait30Sec",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait30Sec": {
      "main": [
        [
          {
            "node": "SplitBatch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SplitBatch": {
      "main": [
        [],
        [
          {
            "node": "Analyze audio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IsAudioCheck": {
      "main": [
        [
          {
            "node": "DownloadFileUploaded",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze audio": {
      "main": [
        [
          {
            "node": "ParseJsonOutput",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ParseJsonOutput": {
      "main": [
        [
          {
            "node": "SaveInfo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DownloadFileUploaded": {
      "main": [
        [
          {
            "node": "SplitBatch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "TriggerGDriveFolderChange": {
      "main": [
        [
          {
            "node": "IsAudioCheck",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}