AutomationFlowsSocial Media › Youtube Optimization Automation: Google Sheets + Deepseek Integration

Youtube Optimization Automation: Google Sheets + Deepseek Integration

ByJacob @jacobgad on n8n.io

Unlock the full potential of your YouTube channel with our powerful integration that connects Google Sheets and DeepSeek AI — designed to skyrocket your video visibility and engagement without manual hassle.

Event trigger★★★★☆ complexityAI-powered12 nodesGoogle SheetsHTTP RequestLm Chat Deep SeekChain Llm
Social Media Trigger: Event Nodes: 12 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #5229 — we link there as the canonical source.

This workflow follows the Chainllm → 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
{
  "id": "wSJzfPqFnJgQoet0",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Youtube optimalization",
  "tags": [],
  "nodes": [
    {
      "id": "c04d2583-25b6-4875-9bef-190d43b3ba55",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "12b1cb02-995c-490b-a1be-3f53831fa2ca",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        220,
        0
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "Pending",
              "lookupColumn": "Status"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 46645040,
          "cachedResultUrl": "",
          "cachedResultName": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1zoIIfA03no9Q_huenS6qYrDFKdhrf1kFijDEHoiBZdk",
          "cachedResultUrl": "",
          "cachedResultName": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "e58439a8-5add-4ff3-87cc-dfac283b8848",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        440,
        0
      ],
      "parameters": {
        "url": "={{ $json.Url }}",
        "options": {},
        "jsonHeaders": "{\n  \"User-Agent\": \"Mozilla/5.0\"\n}",
        "sendHeaders": true,
        "specifyHeaders": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "b2757b85-9256-43af-bd59-4455b30a5d88",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        660,
        0
      ],
      "parameters": {
        "jsCode": "const html = $input.first().json.data;\n\n\nconst match = html.match(/var ytInitialData = (.*?);\\s*<\\/script>/s);\nif (!match) {\n  return [{ json: { error: \"ytInitialData not found\" } }];\n}\n\nlet data;\ntry {\n  data = JSON.parse(match[1]);\n} catch (err) {\n  return [{ json: { error: \"Invalid JSON\", details: err.message } }];\n}\n\nlet title = null;\nlet description = null;\n\n\ntry {\n  const contents = data.contents.twoColumnWatchNextResults.results.results.contents;\n  const videoPrimaryInfo = contents.find(c => c.videoPrimaryInfoRenderer);\n  title = videoPrimaryInfo.videoPrimaryInfoRenderer.title.runs[0].text;\n} catch (e) {\n  title = null;\n}\n\n\nfunction findAttributedDescription(obj) {\n  if (typeof obj !== 'object' || obj === null) return null;\n\n  if (obj.attributedDescription && obj.attributedDescription.content) {\n    return obj.attributedDescription.content;\n  }\n\n  for (const key in obj) {\n    const result = findAttributedDescription(obj[key]);\n    if (result) return result;\n  }\n\n  return null;\n}\n\ndescription = findAttributedDescription(data);\n\nreturn [{\n  json: {\n    title,\n    description\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "d388f1a8-e92f-439b-8fdd-baeda842f703",
      "name": "DeepSeek Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatDeepSeek",
      "position": [
        560,
        220
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "deepSeekApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b8b37c7f-10ed-48e3-9681-74f1b4eabcc8",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        1400,
        -20
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3.2
    },
    {
      "id": "52da4d3e-48d6-4cd3-b52a-cd07a9d6df77",
      "name": "Update row in sheet1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1720,
        -20
      ],
      "parameters": {
        "columns": {
          "value": {
            "Url": "={{ $('Get row(s) in sheet').item.json.Url }}",
            "Etap": "=Done",
            "New Title": "={{ $json.data[0].newTitle }}",
            "Old Title": "={{ $json.data[2].title }}",
            "New Description": "={{ $json.data[1].newDescription }}",
            "Old Description": "={{ $json.data[2].description }}"
          },
          "schema": [
            {
              "id": "Url",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "keyword",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "keyword",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Old Title",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Old Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "New Title",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "New Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Old Description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Old Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "New Description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "New Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "All Keywords",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "All Keywords",
              "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": [
            "Url"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 46645040,
          "cachedResultUrl": "",
          "cachedResultName": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1zoIIfA03no9Q_huenS6qYrDFKdhrf1kFijDEHoiBZdk",
          "cachedResultUrl": "",
          "cachedResultName": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "1be2ad4b-c29a-43af-9ac5-24eee218aee6",
      "name": "Code1",
      "type": "n8n-nodes-base.code",
      "position": [
        1140,
        0
      ],
      "parameters": {
        "jsCode": "\nconst rawText = items[0].json.text;\n\n\nconst parsed = JSON.parse(rawText);\n\n\nreturn [{ json: parsed }];"
      },
      "typeVersion": 2
    },
    {
      "id": "ad7d912a-7cbc-4552-ad21-2a7ab1455c05",
      "name": "Code2",
      "type": "n8n-nodes-base.code",
      "position": [
        1140,
        160
      ],
      "parameters": {
        "jsCode": "\nconst rawText = items[0].json.text;\n\n\nconst parsed = JSON.parse(rawText);\n\n\nreturn [{ json: parsed }];"
      },
      "typeVersion": 2
    },
    {
      "id": "e7f50baa-570d-4426-b5ec-56ef0272bf20",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1540,
        -20
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "6dc22bd3-93eb-4c00-b230-19981f12b7a1",
      "name": "New Title Generating",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        820,
        0
      ],
      "parameters": {
        "text": "=You are a YouTube SEO and copywriting expert.\n\nI will give you:\n- the current (old) video title,\n- the main keyword we want to rank for.\n\nYour job is to rewrite the title to:\n1. Be **more attention-grabbing** (clickable / curiosity-driven),\n2. Include the **given keyword naturally** (for SEO),\n3. Stay relevant to the original title's topic,\n5. Use power words, numbers, questions, or hooks where possible.\n\nOutput only 3 optimized YouTube titles. Number them. Do not add anything else.\n\nOld title: \"{{ $json.title }}\"\nKeyword: \"{{ $('Get row(s) in sheet').item.json.keyword }}\"\n\nVery important: Output only a **valid single-line JSON** with a key called `newTitle`. Do not use markdown, do not include explanations, lists, or comments.\n\nFormat example:\n{\"newTitle\": \"...\"}",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "Very important: Output only a **valid single-line JSON** with a key called `newTitle`. Do not use markdown, do not include explanations, lists, or comments.  Format example: {\"newTitle\": \"...\"}"
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.7,
      "alwaysOutputData": false
    },
    {
      "id": "f19b8383-9fe4-4ae2-9c66-5743f734d3b8",
      "name": "New Description Generating",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        820,
        160
      ],
      "parameters": {
        "text": "=You are an expert in YouTube SEO and copywriting.\n\nYour task is to rewrite a YouTube video description using the following inputs:\n- The **original description**\n- The **main keyword** we want to rank for\n\nInstructions:\n1. Keep the original **timeline section** exactly as it is (do not change order or content).\n2. Improve the rest of the description to:\n   - Be more **engaging and persuasive** (increase watch time and clicks)\n   - Naturally include the **given keyword** for better SEO\n   - Encourage viewers to subscribe, comment, or check other content\n   - Use line breaks, emojis (optionally), and formatting for readability\n3. Output the final version as plain text. Do not explain anything.\n4. The new description should be max 1500 characters if possible.\n\n---\n\nOriginal description:\n\"\"\"\n{{ $json.description }}\n\"\"\"\n\nKeyword: \"{{ $('Get row(s) in sheet').item.json.keyword }}\"\n\n Return in this JSON format:\n{\n  \"newDescription\": \"...\"\n}",
        "batching": {},
        "promptType": "define"
      },
      "typeVersion": 1.7
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "80a821b7-719c-4fc0-bed7-698c2f17dc5a",
  "connections": {
    "Code": {
      "main": [
        [
          {
            "node": "New Title Generating",
            "type": "main",
            "index": 0
          },
          {
            "node": "New Description Generating",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Code1": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code2": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Update row in sheet1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DeepSeek Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "New Title Generating",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "New Description Generating",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Title Generating": {
      "main": [
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Description Generating": {
      "main": [
        [
          {
            "node": "Code2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

Unlock the full potential of your YouTube channel with our powerful integration that connects Google Sheets and DeepSeek AI — designed to skyrocket your video visibility and engagement without manual hassle.

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

More Social Media workflows → · Browse all categories →

Related workflows

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

Social Media

Tired of manually watching long YouTube videos just to extract the main points?

Lm Chat Deep Seek, Chain Llm, Google Sheets +1
Social Media

This n8n workflow template automates the entire process of publishing Instagram Reels from content stored in Google Sheets and Google Drive. It's designed for content creators, social media managers,

Agent, Airtable, Facebook Graph Api +8
Social Media

For content creators, marketers, and video strategists who want to transform YouTube competitors' video transcripts into production-ready content assets using AI-powered automation.

HTTP Request, Google Sheets, Google Sheets Trigger +2
Social Media

YouTube AI analys. Uses youTube, httpRequest, googleSheets, lmChatOpenRouter. Scheduled trigger; 55 nodes.

YouTube, HTTP Request, Google Sheets +2
Social Media

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

@Blotato/N8N Nodes Blotato, Google Sheets, OpenAI +8