Workflow n8n

Automatisation Google Sheets avec n8n : gestion de l'historique chatbot

Ce workflow n8n a pour objectif d'automatiser la gestion de l'historique des interactions d'un chatbot via Google Sheets. Dans un contexte où les entreprises cherchent à améliorer leur service client, ce type d'automatisation permet de conserver une trace des échanges, facilitant ainsi l'analyse et l'amélioration continue des réponses fournies par le chatbot. Les cas d'usage incluent la collecte de données pour des rapports, l'analyse des performances du chatbot et l'optimisation des interactions avec les utilisateurs. Le workflow commence par un déclencheur de type Webhook qui reçoit les messages du chatbot. Ensuite, un agent AI traite ces messages grâce au modèle Google Gemini. Les données sont ensuite préparées et enregistrées dans Google Sheets, permettant de garder un historique des conversations. Des notes autocollantes sont également créées pour visualiser les informations clés. Ce processus est complété par des requêtes HTTP pour enrichir les données. Les bénéfices business incluent une meilleure compréhension des besoins des utilisateurs, une optimisation des réponses du chatbot et une réduction du temps consacré à la gestion manuelle des historiques. En intégrant cette automatisation n8n, les entreprises peuvent ainsi améliorer leur efficacité opérationnelle et leur réactivité face aux demandes des clients.

Tags clés :automatisationGoogle Sheetschatbotn8nhistorique
Catégorie: Webhook · Tags: automatisation, Google Sheets, chatbot, n8n, historique0

Workflow n8n Google Sheets, chatbot, historique : vue d'ensemble

Schéma des nœuds et connexions de ce workflow n8n, généré à partir du JSON n8n.

Workflow n8n Google Sheets, chatbot, historique : détail des nœuds

  • Sticky Note7

    Ce noeud crée une note autocollante avec une largeur et un contenu spécifiés.

Inscris-toi pour voir l'intégralité du workflow

Inscription gratuite

S'inscrire gratuitementBesoin d'aide ?
{
  "id": "[CENSORED]",
  "meta": {
    "instanceId": "[CENSORED]",
    "templateCredsSetupCompleted": true
  },
  "name": "(G) LineChatBot + Google Sheets (as a memory)",
  "tags": [
    {
      "id": "[CENSORED]",
      "name": "Guitar",
      "createdAt": "2025-04-18T08:59:48.308Z",
      "updatedAt": "2025-04-18T08:59:48.308Z"
    }
  ],
  "nodes": [
    {
      "id": "[CENSORED]",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        560,
        -500
      ],
      "webhookId": "[CENSORED]",
      "parameters": {
        "path": "guitarpa",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2
    },
    {
      "id": "[CENSORED]",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        460,
        -220
      ],
      "parameters": {
        "text": "={{ $json.Prompt }}",
        "options": {
          "systemMessage": "=You are a helpful assistant. Your name is \"ลลิตา\". You will help me in everything I need. You will answer based on user language. You are an AI Agent operating in the Thailand time zone (Asia/Bangkok, UTC+7). Today is {{ $now }}."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.8
    },
    {
      "id": "[CENSORED]",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        460,
        -20
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.0-flash-001"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "[CENSORED]",
          "name": "Guitar's Gemini ([CENSORED_EMAIL])"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "[CENSORED]",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        780,
        -500
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "[CENSORED]",
              "name": "body.events[0].message.text",
              "type": "string",
              "value": "={{ $('Webhook').item.json.body.events[0].message.text }}"
            },
            {
              "id": "[CENSORED]",
              "name": "body.events[0].replyToken",
              "type": "string",
              "value": "={{ $('Webhook').item.json.body.events[0].replyToken }}"
            },
            {
              "id": "[CENSORED]",
              "name": "body.events[0].source.userId",
              "type": "string",
              "value": "={{ $json.body.events[0].source.userId }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "[CENSORED]",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1276,
        -220
      ],
      "parameters": {
        "url": "https://api.line.me/v2/bot/message/reply",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n    \"replyToken\": \"{{ $('Edit Fields').item.json.body.events[0].replyToken }}\",\n    \"messages\": [\n        {\n            \"type\": \"text\",\n            \"text\": \"{{ $('AI Agent').item.json.output.replaceAll('\\t', ' ').replaceAll('\\\"', '\\\\\\\"').replaceAll('\\n', '\\\\n').trim() || 'No response available.' }}\"\n        }\n    ]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer [CENSORED]"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "[CENSORED]",
      "name": "Get History",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1000,
        -500
      ],
      "parameters": {
        "options": {
          "outputFormatting": {
            "values": {
              "date": "FORMATTED_STRING",
              "general": "UNFORMATTED_VALUE"
            }
          },
          "returnFirstMatch": true,
          "dataLocationOnSheet": {
            "values": {
              "rangeDefinition": "detectAutomatically"
            }
          }
        },
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $('Webhook').item.json.body.events[0].source.userId }}",
              "lookupColumn": "UserID "
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "[CENSORED]",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "[CENSORED]"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "[CENSORED]",
          "name": "[Guitar] Google Sheets ([CENSORED_EMAIL])"
        }
      },
      "notesInFlow": false,
      "typeVersion": 4.5,
      "alwaysOutputData": true
    },
    {
      "id": "[CENSORED]",
      "name": "Prepare Prompt",
      "type": "n8n-nodes-base.set",
      "position": [
        1220,
        -500
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "[CENSORED]",
              "name": "Prompt",
              "type": "string",
              "value": "={{\n  \"คุณคือลลิตา แชทบอทภาษาไทยที่สุภาพและเป็นมิตร ตอบตามบริบทของการสนทนา:\\n\" +\n\n  ($('Get History').item.json.History_Archive_1 || \"\") +\n  (($('Get History').item.json.History_Archive_1) ? \"\\n\" : \"\") +\n\n  ($('Get History').item.json.History_Archive_2 || \"\") +\n  (($('Get History').item.json.History_Archive_2) ? \"\\n\" : \"\") +\n\n  ($('Get History').item.json.History_Archive_3 || \"\") +\n  (($('Get History').item.json.History_Archive_3) ? \"\\n\" : \"\") +\n\n  ($('Get History').item.json.History_Archive_4 || \"\") +\n  (($('Get History').item.json.History_Archive_4) ? \"\\n\" : \"\") +\n\n  ($('Get History').item.json.History || \"\") +\n  (($('Get History').item.json.History) ? \"\\n\" : \"\") +\n\n  \"ผู้ใช้: \" + $('Edit Fields').item.json.body.events[0].message.text + \"\\nลลิตา: \"\n}}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "[CENSORED]",
      "name": "Save History",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1056,
        -220
      ],
      "parameters": {
        "columns": {
          "value": {
            "History": "={{ $('Split History').item.json.historyToSave }}",
            "UserID ": "={{ $('Edit Fields').item.json.body.events[0].source.userId }}",
            "LastUpdated": "={{ new Date().toISOString() }}",
            "History_Archive_1": "={{ $('Split History').item.json.historyArchive1 }}",
            "History_Archive_2": "={{ $('Split History').item.json.historyArchive2 }}",
            "History_Archive_3": "={{ $('Split History').item.json.historyArchive3 }}",
            "History_Archive_4": "={{ $('Split History').item.json.historyArchive4 }}"
          },
          "schema": [
            {
              "id": "UserID ",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "UserID ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "History",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "History",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LastUpdated",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "LastUpdated",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "History_Archive_1",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "History_Archive_1",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "History_Archive_2",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "History_Archive_2",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "History_Archive_3",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "History_Archive_3",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "History_Archive_4",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "History_Archive_4",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "UserID "
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "[CENSORED]",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "[CENSORED]"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "[CENSORED]",
          "name": "[Guitar] Google Sheets ([CENSORED_EMAIL])"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "[CENSORED]",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        460,
        -560
      ],
      "parameters": {
        "content": "### Connect to Line Official Account's API"
      },
      "typeVersion": 1
    },
    {
      "id": "[CENSORED]",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        740,
        -560
      ],
      "parameters": {
        "width": 180,
        "content": "Prepare the data"
      },
      "typeVersion": 1
    },
    {
      "id": "[CENSORED]",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        -560
      ],
      "parameters": {
        "width": 180,
        "content": "Retrieve chat history"
      },
      "typeVersion": 1
    },
    {
      "id": "[CENSORED]",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1180,
        -560
      ],
      "parameters": {
        "width": 180,
        "content": "Give our AI previous chat history"
      },
      "typeVersion": 1
    },
    {
      "id": "[CENSORED]",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        460,
        -280
      ],
      "parameters": {
        "content": "Get input with this command.   \"{{ $json.Prompt }}\""
      },
      "typeVersion": 1
    },
    {
      "id": "[CENSORED]",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        780,
        -280
      ],
      "parameters": {
        "width": 180,
        "content": "Split history into small chunks (data cleaning)"
      },
      "typeVersion": 1
    },
    {
      "id": "[CENSORED]",
      "name": "Split History",
      "type": "n8n-nodes-base.code",
      "position": [
        840,
        -220
      ],
      "parameters": {
        "jsCode": "// Get the current history, new message, and response\nlet history = $('Get History').item.json.History || '';\nlet message = $('Edit Fields').item.json.body.events[0].message.text;\nlet response = $json.output;\nlet newExchange = `ผู้ใช้: ${message}\\nลลิตา: ${response}`;\nlet updatedHistory = history + (history ? '\\n' : '') + newExchange;\n\n// Threshold: 70% of Google Sheets cell limit (50,000 characters * 0.7 = 35,000)\nconst threshold = 35000;\nlet historyToSave = updatedHistory;\nlet archive1 = $('Get History').item.json.History_Archive_1 || '';\nlet archive2 = $('Get History').item.json.History_Archive_2 || '';\nlet archive3 = $('Get History').item.json.History_Archive_3 || '';\nlet archive4 = $('Get History').item.json.History_Archive_4 || '';\n\n// If history exceeds threshold, split it\nif (updatedHistory.length > threshold) {\n  // Keep the last 17,500 characters in History (half of threshold for balance)\n  const keepLength = 17500;\n  const archiveChunk = updatedHistory.substring(0, updatedHistory.length - keepLength);\n  historyToSave = updatedHistory.substring(updatedHistory.length - keepLength);\n\n  // Distribute to archive cells, ensuring none exceed 35,000 characters\n  if (archive1.length < threshold) {\n    archive1 = (archive1 ? archive1 + '\\n' : '') + archiveChunk;\n    if (archive1.length > threshold) {\n      const excess = archive1.substring(threshold);\n      archive1 = archive1.substring(0, threshold);\n      if (archive2.length < threshold) {\n        archive2 = (archive2 ? archive2 + '\\n' : '') + excess;\n      }\n    }\n  }\n  if (archive2.length < threshold && archive1.length >= threshold) {\n    archive2 = (archive2 ? archive2 + '\\n' : '') + archiveChunk;\n    if (archive2.length > threshold) {\n      const excess = archive2.substring(threshold);\n      archive2 = archive2.substring(0, threshold);\n      if (archive3.length < threshold) {\n        archive3 = (archive3 ? archive3 + '\\n' : '') + excess;\n      }\n    }\n  }\n  if (archive3.length < threshold && archive2.length >= threshold) {\n    archive3 = (archive3 ? archive3 + '\\n' : '') + archiveChunk;\n    if (archive3.length > threshold) {\n      const excess = archive3.substring(threshold);\n      archive3 = archive3.substring(0, threshold);\n      if (archive4.length < threshold) {\n        archive4 = (archive4 ? archive4 + '\\n' : '') + excess;\n      }\n    }\n  }\n  if (archive4.length < threshold && archive3.length >= threshold) {\n    archive4 = (archive4 ? archive4 + '\\n' : '') + archiveChunk;\n    if (archive4.length > threshold) {\n      archive4 = archive4.substring(0, threshold);\n    }\n  }\n}\n\n// Return the values to update\nreturn [\n  {\n    json: {\n      historyToSave: historyToSave,\n      historyArchive1: archive1,\n      historyArchive2: archive2,\n      historyArchive3: archive3,\n      historyArchive4: archive4,\n      lastUpdated: new Date().toISOString()\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "[CENSORED]",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1000,
        -280
      ],
      "parameters": {
        "width": 180,
        "content": "Save to Google Sheets"
      },
      "typeVersion": 1
    },
    {
      "id": "[CENSORED]",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1220,
        -280
      ],
      "parameters": {
        "width": 180,
        "content": "Send it back to Line"
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "[CENSORED]",
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Split History",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Get History",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get History": {
      "main": [
        [
          {
            "node": "Prepare Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save History": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split History": {
      "main": [
        [
          {
            "node": "Save History",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Prompt": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}

Workflow n8n Google Sheets, chatbot, historique : pour qui est ce workflow ?

Ce workflow s'adresse aux entreprises qui utilisent des chatbots pour interagir avec leurs clients, notamment dans les secteurs du service client et du e-commerce. Il est idéal pour les équipes techniques et marketing qui souhaitent automatiser la gestion des données de conversation tout en ayant des compétences intermédiaires en outils d'automatisation.

Workflow n8n Google Sheets, chatbot, historique : problème résolu

Ce workflow résout le problème de la gestion manuelle des historiques de conversations de chatbot, qui peut être chronophage et sujet à des erreurs. En automatisant ce processus, les entreprises évitent des pertes de temps et réduisent le risque de perte d'informations critiques. Les utilisateurs bénéficient d'une meilleure traçabilité des interactions, ce qui leur permet d'améliorer continuellement les performances de leur chatbot.

Workflow n8n Google Sheets, chatbot, historique : étapes du workflow

Étape 1 : Le workflow est déclenché par un Webhook qui reçoit les messages du chatbot.

  • Étape 1 : Un agent AI analyse ces messages à l'aide du modèle Google Gemini pour en extraire des informations pertinentes.
  • Étape 2 : Les données sont ensuite traitées et préparées pour être enregistrées.
  • Étape 3 : Les informations sont sauvegardées dans Google Sheets pour conserver un historique des interactions.
  • Étape 4 : Des notes autocollantes sont créées pour visualiser les points clés des conversations.
  • Étape 5 : Des requêtes HTTP peuvent être effectuées pour enrichir les données si nécessaire.

Workflow n8n Google Sheets, chatbot, historique : guide de personnalisation

Pour personnaliser ce workflow, vous pouvez modifier l'URL du Webhook pour l'adapter à votre système de chatbot. Il est également possible de changer le nom de la feuille Google Sheets et d'ajuster les colonnes selon vos besoins. Si vous souhaitez intégrer d'autres outils, vous pouvez ajouter des noeuds HTTP pour des appels API supplémentaires. Assurez-vous de sécuriser votre Webhook avec des authentifications appropriées et de monitorer les performances du flux pour garantir son bon fonctionnement.