{
  "id": "h7TfGnFhrWa9HgvM",
  "name": "Instagram Reels AI Tracker 1.0",
  "tags": [],
  "nodes": [
    {
      "id": "0c4bb194-e782-4923-946d-f3939d8a68a5",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -448,
        -80
      ],
      "parameters": {
        "width": 480,
        "height": 896,
        "content": "## Instagram Reels AI Tracker\n\n### How it works\n\n1. It starts on a schedule, acquires a run lock, and stops early with a Telegram notice if another run is already active.\n2. It loads Instagram account settings from Google Sheets, filters accounts by check interval, and loops through the accounts that should be checked now.\n3. For each active account, it scrapes recent Instagram reels, validates the scrape, filters video reels, and prepares only new items for per-reel processing.\n4. It loops through reels, skips items already recorded, stores new rows in Google Sheets, generates transcripts with Apify, and analyzes valid transcript text with OpenAI.\n5. It writes success, no-text, duplicate, and failure outcomes back to sheets, using wait nodes to continue the batch loops safely.\n6. It aggregates account-level results, builds a run summary, sends a Telegram report, and updates account check-in timestamps for the next run.\n\n### Setup steps\n\n- - [ ] Connect Google Sheets credentials for reading the account list and updating the Reels Library, Latest Run, and account check-in data.\n- - [ ] Connect Apify credentials and verify the actors/tasks used for scraping recent reels and generating transcripts.\n- - [ ] Connect OpenAI credentials and confirm the model and prompt in the reel analysis node match the desired output language and format.\n- - [ ] Connect Telegram credentials and set the target chat/channel for lock alerts and run summary notifications.\n- - [ ] Review the workflow settings node values, especially the Google Sheet link, output language, max reels per account per run, and any run ID logic.\n- - [ ] Confirm the source sheet contains the expected account fields, including usernames and check interval timestamps used by the filtering code nodes.\n\n### Customization\n\nYou can customize the account recheck interval logic, the scrape date threshold, the maximum reels processed per account, the duplicate-detection rules against Google Sheets, the transcript-required condition before AI analysis, and the Telegram summary/error message formatting."
      },
      "typeVersion": 1
    },
    {
      "id": "98c92fa7-91d0-479c-894d-f1986cfcd0a3",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        112,
        224
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 304,
        "content": "## Trigger and run lock\n\nStarts the workflow on schedule, acquires a lock, and decides whether the run can proceed."
      },
      "typeVersion": 1
    },
    {
      "id": "b9bb786d-d513-44e2-8ecd-91880c622219",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1808,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 320,
        "content": "## Lock conflict alert\n\nFormats and sends the Telegram message when the workflow is already running and the lock blocks a new run."
      },
      "typeVersion": 1
    },
    {
      "id": "9149c54d-c595-4851-9654-f0f7c9541790",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        784,
        272
      ],
      "parameters": {
        "color": 7,
        "height": 336,
        "content": "## Workflow settings setup\n\nInitializes global run parameters such as run ID, output language, sheet link, and per-run reel limits."
      },
      "typeVersion": 1
    },
    {
      "id": "fa7cf40e-aaed-4a61-96e0-77cd5df7a72b",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1056,
        288
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 320,
        "content": "## Load account sheet\n\nReads the source Google Sheet and prepares filter values needed to decide which accounts should be checked."
      },
      "typeVersion": 1
    },
    {
      "id": "24e71e5f-5857-4f29-9a07-5d1b34867ec3",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1504,
        288
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 320,
        "content": "## Filter eligible accounts\n\nApplies the account check-interval logic and branches depending on whether any accounts are ready for processing."
      },
      "typeVersion": 1
    },
    {
      "id": "11987b05-d434-49e1-b3a8-fe0588c46347",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1952,
        112
      ],
      "parameters": {
        "color": 7,
        "height": 384,
        "content": "## No accounts notification\n\nFormats and sends an informational Telegram message when there are no checkable users for this run."
      },
      "typeVersion": 1
    },
    {
      "id": "78e80f22-1237-40cc-aa78-a473b8a1b741",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2176,
        512
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 400,
        "content": "## Account loop and scrape\n\nLoops through active accounts, aggregates account-level results in parallel, and scrapes recent reels from Apify for each account."
      },
      "typeVersion": 1
    },
    {
      "id": "30d7e146-7156-4c7f-9af3-4f4b33f439a3",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2656,
        224
      ],
      "parameters": {
        "color": 7,
        "width": 1024,
        "height": 496,
        "content": "## Run summary and account updates\n\nDeduplicates aggregated data, builds the run summary, sends the Telegram report, and updates account check-in times."
      },
      "typeVersion": 1
    },
    {
      "id": "22f14c1c-cdce-463a-b4bf-98b7e773f331",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2672,
        720
      ],
      "parameters": {
        "color": 7,
        "width": 1776,
        "height": 288,
        "content": "## Scrape validation branch\n\nValidates each account scrape result and routes failed scrapes into a status item that can re-enter the account loop after waiting."
      },
      "typeVersion": 1
    },
    {
      "id": "7a2fb76b-1c1f-4a65-bb3d-bffa19ea90a4",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2672,
        1040
      ],
      "parameters": {
        "color": 7,
        "width": 704,
        "height": 608,
        "content": "## Reel filtering and lookup\n\nKeeps only video reels, checks existing sheet records, filters by date, and prepares context fields before merging the reel data streams."
      },
      "typeVersion": 1
    },
    {
      "id": "b6adf064-8d4f-41db-8cf7-eccede01df93",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3408,
        1040
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 336,
        "content": "## Merge reel payloads\n\nMerges filtered reel inputs, resets the fields, and reshapes the payload before entering the per-reel loop."
      },
      "typeVersion": 1
    },
    {
      "id": "b824c7c5-35b7-4eee-be4a-0796c346e951",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3984,
        1744
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 432,
        "content": "## Reel loop control\n\nIterates through reels one by one and uses a wait step to continue the loop between items and after account-level failures."
      },
      "typeVersion": 1
    },
    {
      "id": "09bb0216-1d75-46e3-8340-e63e9e5242ea",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4496,
        1040
      ],
      "parameters": {
        "color": 7,
        "width": 2176,
        "height": 272,
        "content": "## Duplicate reel handling\n\nFilters out already crawled reels, checks whether a row already exists in Google Sheets, and emits an informational duplicate status when applicable."
      },
      "typeVersion": 1
    },
    {
      "id": "740091a8-1775-48a9-9935-f3d60bf60cb6",
      "name": "Sticky Note14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4624,
        1376
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 320,
        "content": "## Transcript preparation\n\nCreates or updates the reel row in Google Sheets, generates a transcript with Apify, and decides whether transcript text is available for AI analysis."
      },
      "typeVersion": 1
    },
    {
      "id": "f831518e-f85f-4a67-bde8-d28417202e9b",
      "name": "Sticky Note15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5344,
        1360
      ],
      "parameters": {
        "color": 7,
        "width": 928,
        "height": 304,
        "content": "## No transcript failure path\n\nBuilds a no-text error message, updates the failure row in the reels sheet, writes a Latest Run record, and marks the reel as a no-text error."
      },
      "typeVersion": 1
    },
    {
      "id": "584ad820-5b52-4e7e-a2eb-b6da34877d1f",
      "name": "Sticky Note16",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5280,
        1696
      ],
      "parameters": {
        "color": 7,
        "width": 992,
        "height": 304,
        "content": "## AI success writeback\n\nAnalyzes transcript content with OpenAI, updates the success row in the sheet, adds the successful run record, and emits a success status."
      },
      "typeVersion": 1
    },
    {
      "id": "1aa5697c-5ddc-4c82-b37d-1fb825b1409d",
      "name": "Every Hour Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        160,
        352
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours"
            }
          ]
        }
      },
      "typeVersion": 1.3,
      "alwaysOutputData": false
    },
    {
      "id": "1854bc07-d185-493f-8fea-8c7cce82d0cf",
      "name": "Read Accounts from Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1104,
        448
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "YES",
              "lookupColumn": "active"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Accounts"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $json.google_sheet_share_link }}"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "notesInFlow": false,
      "retryOnFail": true,
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "ca5f614e-1e44-4fef-8f1e-2c0e54cc3659",
      "name": "Wait 2 Seconds",
      "type": "n8n-nodes-base.wait",
      "position": [
        4304,
        1536
      ],
      "parameters": {
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "22d2b29d-e667-4963-bef2-c24147921a2c",
      "name": "Send Workflow Status to Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        2240,
        -128
      ],
      "parameters": {
        "text": "={{ $json.message }}",
        "chatId": "123456789",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "retryOnFail": true,
      "typeVersion": 1.2
    },
    {
      "id": "06cda903-e268-49cd-b455-14c34cfa9ec9",
      "name": "Format No Accounts Message",
      "type": "n8n-nodes-base.code",
      "position": [
        2000,
        320
      ],
      "parameters": {
        "jsCode": "const workflowStaticData = $getWorkflowStaticData('global');\ndelete workflowStaticData.isRunning;\ndelete workflowStaticData.startTime;\ndelete workflowStaticData.executionId;\nreturn [{ json: { message: \"There is no available data in Accounts Google Sheets.\" } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "d90d7284-4f4a-41a0-9432-4f3bbcd93dc1",
      "name": "Check Reel Exists in Sheets",
      "type": "n8n-nodes-base.if",
      "position": [
        4752,
        1168
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "0a655b37-bcf2-476c-85b9-9b2d2aeb8869",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "crawled"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "34b2ecfc-29a7-4b98-a402-6911d7f463f0",
      "name": "Set Account Filter Values",
      "type": "n8n-nodes-base.set",
      "position": [
        1328,
        448
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b0a9baef-b0e1-49ef-8630-104f2f3cfc94",
              "name": "=scrape_newer_than",
              "type": "string",
              "value": "={{ $ifEmpty($json.last_checked_at, $now.minus({ days: 3 }).toUTC().toFormat(\"yyyy-MM-dd'T'HH:mm:ss'Z'\")) }}"
            },
            {
              "id": "4fc3b01b-5653-4979-bda2-105ad11d7ce7",
              "name": "=account_checked_at",
              "type": "string",
              "value": "={{ $now.toUTC().toFormat(\"yyyy-MM-dd'T'HH:mm:ss'Z'\") }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "166c59f2-ffc0-44ab-956b-ad27dc99ea2e",
      "name": "Update Account Check Timestamp",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueRegularOutput",
      "position": [
        3552,
        320
      ],
      "parameters": {
        "columns": {
          "value": {
            "row_number": 0,
            "last_checked_at": "={{ $json.account_checked_at }}",
            "instagram_username": "={{ $json.account }}"
          },
          "schema": [
            {
              "id": "instagram_username",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "instagram_username",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "account_name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "account_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "category",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "active",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "active",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_checked_at",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "last_checked_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "instagram_username"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Accounts"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Reset Temp Parameters').last().json.google_sheet_share_link }}"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.7
    },
    {
      "id": "81c8a055-87ab-4efe-a869-1c1e8e0a7edf",
      "name": "If Checkable Accounts Exist",
      "type": "n8n-nodes-base.if",
      "position": [
        1776,
        448
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8e4a3637-f404-4fd7-bdee-a1c2d065232d",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "leftValue": "={{ Object.keys($json).length }}",
              "rightValue": 1
            }
          ]
        }
      },
      "typeVersion": 2.3,
      "alwaysOutputData": false
    },
    {
      "id": "9013c232-a437-401e-b9e3-160005c162a7",
      "name": "Wait 1 Second",
      "type": "n8n-nodes-base.wait",
      "position": [
        6512,
        2096
      ],
      "parameters": {
        "amount": 1
      },
      "typeVersion": 1.1
    },
    {
      "id": "41e4d40e-50a2-4781-b1e3-c813cdb1127e",
      "name": "Upsert Reel in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        4656,
        1520
      ],
      "parameters": {
        "columns": {
          "value": {
            "run_id": "={{ $('Reset Temp Parameters').last().json.run_id }}",
            "caption": "={{ $json.caption }}",
            "reel_id": "={{ $json.pk }}",
            "reel_url": "={{ $json.url }}",
            "captured_at": "={{ $now.toUTC().toFormat(\"yyyy-MM-dd'T'HH:mm:ss'Z'\") }}",
            "account_name": "={{ $json.ownerFullName }}",
            "published_at": "={{ new Date(String($json.timestamp).length === 10 ? Number($json.timestamp) * 1000 : Number($json.timestamp)).toISOString() }}",
            "process_status": "PROCESSING",
            "instagram_username": "={{ $json.ownerUsername }}"
          },
          "schema": [
            {
              "id": "reel_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "reel_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "reel_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "reel_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "instagram_username",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "instagram_username",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "account_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "account_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "published_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "published_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "run_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "run_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "captured_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "captured_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "caption",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "caption",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "transcript",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "transcript",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "main_topic",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "main_topic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hook",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "hook",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hook_type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "hook_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CTA_type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "CTA_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "content_angle",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "content_angle",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "reusable_idea",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "reusable_idea",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tags",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "tags",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "process_status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "process_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "error_message",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "error_message",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "reel_id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Reels Library"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Reset Temp Parameters').last().json.google_sheet_share_link }}"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.7
    },
    {
      "id": "ccf568b4-7606-41b3-88a8-c7b521984b10",
      "name": "If Transcript Available",
      "type": "n8n-nodes-base.if",
      "position": [
        5104,
        1520
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "963f440e-5778-4f39-8fc8-faae76879f17",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.text }}",
              "rightValue": ""
            },
            {
              "id": "b571973e-5536-45bc-b86e-fe2ec62e41cb",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "leftValue": "={{ $json.text.length }}",
              "rightValue": 20
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "9cc1f9d7-f0dd-4751-a113-44b86afaec94",
      "name": "Merge New and Existing Reel Data",
      "type": "n8n-nodes-base.code",
      "position": [
        3904,
        1184
      ],
      "parameters": {
        "jsCode": "const data1 = $('Filter Video Reels').all();\nconst data2 = $('Read Existing Reels from Sheets').all();\nconst reelIds = Array.isArray(data2) ? data2.map(item => item.json?.reel_id).filter(Boolean) : [];\nreturn data1.map((item, index) => ({\n  jiedian1: item.json,\n  jiedian2: reelIds\n}));"
      },
      "executeOnce": false,
      "typeVersion": 2
    },
    {
      "id": "2834f1c0-62ae-4e7b-9a3b-85e4bd0a6183",
      "name": "Prepare Reel Parameters",
      "type": "n8n-nodes-base.set",
      "position": [
        3104,
        1472
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "92e4ba70-ddb6-4c4c-89fe-a539fccce6ab",
              "name": "google_sheet_share_link",
              "type": "string",
              "value": "={{ $('Set Global Workflow Settings').item.json.google_sheet_share_link }}"
            },
            {
              "id": "8ef30ee1-7a2d-4046-83c0-ab450ad42800",
              "name": "run_id",
              "type": "string",
              "value": "={{ $('Set Global Workflow Settings').item.json.run_id }}"
            },
            {
              "id": "7d8d9a84-87c9-40a6-ac61-987b9ec3740e",
              "name": "instagram_username",
              "type": "string",
              "value": "={{ $('Loop Over Active Accounts').item.json.instagram_username }}"
            },
            {
              "id": "2bc3a5c0-853c-4cfe-b48c-35d01a20a5d2",
              "name": "output_language",
              "type": "string",
              "value": "={{ $('Set Global Workflow Settings').item.json.output_language }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "2e66259d-f095-4fcc-aa1a-6e47809b5014",
      "name": "Reset Temp Parameters",
      "type": "n8n-nodes-base.set",
      "position": [
        3680,
        1184
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": []
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "70726b03-cd54-4913-91d6-4b09133e9c4c",
      "name": "Generate Transcript with Apify",
      "type": "@apify/n8n-nodes-apify.apify",
      "position": [
        4864,
        1520
      ],
      "parameters": {
        "actorId": {
          "__rl": true,
          "mode": "list",
          "value": "S9A11NvceWaGorwwh",
          "cachedResultUrl": "https://console.apify.com/actors/S9A11NvceWaGorwwh/input",
          "cachedResultName": "Instagram Transcript API \u2013 AI Video to Text for Developers (apple_yang/instagram-transcripts-scraper)"
        },
        "timeout": 120,
        "operation": "Run actor and get dataset",
        "customBody": "={\n    \"videoUrl\": \"{{ $json.reel_url }}\",\n    \"sessionid\": \"\"\n}",
        "actorSource": "store"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "retryOnFail": true,
      "typeVersion": 1
    },
    {
      "id": "269d4a88-43a8-452b-a485-f89149fb57c2",
      "name": "Acquire Run Lock Flag",
      "type": "n8n-nodes-base.code",
      "position": [
        384,
        352
      ],
      "parameters": {
        "jsCode": "const workflowStaticData = $getWorkflowStaticData('global');\nconst now = Date.now();\nconst lockTimeout = 30 * 60 * 1000;\n\nif (workflowStaticData.isRunning && workflowStaticData.startTime) {\n  const elapsed = now - workflowStaticData.startTime;\n  \n  if (elapsed < lockTimeout) {\n    return [{ \n      json: { \n        skip: true, \n        reason: \"The workflow is currently running.\",\n        runningSince: new Date(workflowStaticData.startTime).toISOString()\n      } \n    }];\n  } else {\n    delete workflowStaticData.isRunning;\n    delete workflowStaticData.startTime;\n    console.log(\"\u68c0\u6d4b\u5230\u8d85\u65f6\u9501\uff0c\u5f3a\u5236\u91cd\u7f6e\");\n  }\n}\n\nworkflowStaticData.isRunning = true;\nworkflowStaticData.startTime = now;\nworkflowStaticData.executionId = $execution.id;\n\nreturn [{ json: { skip: false, message: \"The workflow has started to run.\" } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "ea2b0f5a-8175-44b3-99b6-d8b201a3dc08",
      "name": "If Workflow Already Running",
      "type": "n8n-nodes-base.if",
      "position": [
        608,
        352
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "d1e47903-9ac3-431b-8991-3527c466e9c0",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.skip }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "d98709d1-e594-4717-b916-eba358e65c9c",
      "name": "Set Global Workflow Settings",
      "type": "n8n-nodes-base.set",
      "position": [
        832,
        448
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "61325c03-7094-4808-8015-68f2706cd043",
              "name": "run_id",
              "type": "string",
              "value": "={{ $now.format('yyyyMMddHHmmss') }}"
            },
            {
              "id": "398213b4-a634-474a-a11c-70d89316f401",
              "name": "output_language",
              "type": "string",
              "value": "English"
            },
            {
              "id": "0cb996fc-b4fe-4ae9-87a8-73c5d49b4ab0",
              "name": "google_sheet_share_link",
              "type": "string",
              "value": "https://docs.google.com/spreadsheets/d/1UjEUnSRWwHaG3c6SCO3PDCvlCRUkNdofzxkSoyBP4FA/edit?gid=0#gid=0"
            },
            {
              "id": "c30c7d1f-52f6-4a94-9c5d-200948b108b7",
              "name": "max_reels_per_account_per_run",
              "type": "number",
              "value": 2
            },
            {
              "id": "814d18ee-c65a-412e-9d32-f71d4ed86877",
              "name": "account_check_interval",
              "type": "number",
              "value": 86400
            }
          ]
        }
      },
      "typeVersion": 3.4,
      "alwaysOutputData": false
    },
    {
      "id": "34dfcef7-4820-49b7-8236-4abb6d084198",
      "name": "Filter Accounts by Check Window",
      "type": "n8n-nodes-base.code",
      "position": [
        1552,
        448
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst checkIntervalSeconds = $('Set Global Workflow Settings').item.json.account_check_interval || 86400;\n\nconst filteredItems = items.filter(item => {\n  const json = item.json;\n  \n  const scrapeNewerThan = json.scrape_newer_than;\n  const accountCheckedAt = json.account_checked_at;\n  \n  if (!scrapeNewerThan || !accountCheckedAt) {\n    return true;\n  }\n  \n  const scrapeTime = new Date(scrapeNewerThan).getTime();\n  const checkedTime = new Date(accountCheckedAt).getTime();\n  \n  const diffInSeconds = (checkedTime - scrapeTime) / 1000;\n  \n  return diffInSeconds >= checkIntervalSeconds;\n});\n\nreturn filteredItems;"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "48bc29b3-4f46-45b7-aeb5-defd60e7e46b",
      "name": "Loop Over Active Accounts",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2272,
        688
      ],
      "parameters": {
        "options": {
          "reset": "={{ $prevNode.name === 'If Checkable Accounts Exist' }}"
        },
        "batchSize": "=1"
      },
      "executeOnce": false,
      "typeVersion": 3,
      "alwaysOutputData": false
    },
    {
      "id": "1528ecdc-65a8-45cd-8046-ee3b4ec684e9",
      "name": "Scrape Recent Reels with Apify",
      "type": "@apify/n8n-nodes-apify.apify",
      "position": [
        2752,
        848
      ],
      "parameters": {
        "actorId": {
          "__rl": true,
          "mode": "list",
          "value": "YZg1Mu5pgHhtbjio4",
          "cachedResultUrl": "https://console.apify.com/actors/YZg1Mu5pgHhtbjio4/input",
          "cachedResultName": "Instagram Post Scraper (apple_yang/instagram-post-scraper)"
        },
        "timeout": 120,
        "operation": "Run actor and get dataset",
        "customBody": "={\n    \"resultsLimit\": {{ $('Set Global Workflow Settings').item.json.max_reels_per_account_per_run }},\n    \"usernames\": [\n        \"{{ $json.instagram_username }}\"\n    ]\n}",
        "actorSource": "store"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1
    },
    {
      "id": "0012ab69-295f-44b7-afdb-321c8d536f7d",
      "name": "OpenAI Reel Content Analysis",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        5328,
        1824
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5.4",
          "cachedResultName": "GPT-5.4"
        },
        "options": {
          "maxTokens": 2048,
          "reasoning": {
            "reasoningOptions": {
              "effort": "low",
              "summary": "none"
            }
          },
          "textFormat": {
            "textOptions": {
              "type": "json_object"
            }
          }
        },
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "You are a social media content analyst.\n\nAnalyze Instagram Reel content and return structured insights for a competitor research tracker.\n\nReturn ONLY valid JSON.\nDo not include markdown.\nDo not include any explanation.\nDo not add any extra fields.\n\nLanguage rules:\n- Use output_language for these fields only:\n  summary, main_topic, hook, reusable_idea, tags\n- Keep these fields in fixed English enum values only:\n  hook_type, CTA_type, content_angle\n\nField requirements:\n- summary: Write a concise 2-4 sentence summary of the Reel.\n- main_topic: A short phrase describing the main topic.\n- hook: Return the most attention-grabbing opening line or opening idea in output_language. If needed, translate or rewrite it into output_language. Do not keep the original language unless output_language matches it.\n- hook_type: Choose only one from:\n  curiosity, pain_point, surprise, authority, story, direct_claim, question, emotional\n- CTA_type: Choose only one from:\n  none, follow, comment, share, click, buy, dm, save\n- content_angle: Choose only one from:\n  educational, storytelling, opinion, promotional, entertainment, lifestyle, personal_brand, product_demo\n- reusable_idea: Write 1-3 sentences describing how this Reel idea could be adapted into a similar piece of content.\n- tags: Return 3-6 short tags as a single comma-separated string in output_language.\n\nIf the transcript is incomplete, still do your best based on the available transcript and caption.\nIf a field is unclear, make the best reasonable inference.\nIf there is no obvious CTA, use \"none\".\n\nReturn this exact JSON structure:\n\n{\n  \"summary\": \"\",\n  \"main_topic\": \"\",\n  \"hook\": \"\",\n  \"hook_type\": \"\",\n  \"CTA_type\": \"\",\n  \"content_angle\": \"\",\n  \"reusable_idea\": \"\",\n  \"tags\": \"\"\n}"
            },
            {
              "content": "=Caption:\n {{ $('Upsert Reel in Sheets').item.json.caption }}\n\nTranscript:\n{{ $('Generate Transcript with Apify').item.json.text }}\n\nOutput language:\n{{ $('Reset Temp Parameters').last().json.output_language }}"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 2.1
    },
    {
      "id": "a1bdea55-da1b-42a8-a75d-25effcd96e71",
      "name": "Build Run Summary Report",
      "type": "n8n-nodes-base.code",
      "position": [
        3152,
        416
      ],
      "parameters": {
        "jsCode": "const inputItems = $input.all();\n\nconst inputData = inputItems.map(item => item.json);\n\nconst totalCount = inputData.length;\nconst uniqueAccounts = [...new Set(inputData.map(item => item.account))];\nconst accountCount = uniqueAccounts.length;\n\nconst pureSuccessItems = inputData.filter(item => item.status === 'success');\nconst crawledItems = inputData.filter(item => item.status === 'crawled');\nconst failedItems = inputData.filter(item => item.status === 'failed');\n\nconst pureSuccessCount = pureSuccessItems.length;\nconst crawledCount = crawledItems.length;\nconst failCount = failedItems.length;\nconst effectiveSuccessCount = pureSuccessCount + crawledCount;\nconst successRate = totalCount > 0 ? ((effectiveSuccessCount / totalCount) * 100).toFixed(1) : '0.0';\n\nconst processedTimes = inputData\n  .map(item => item.processedAt ? new Date(item.processedAt) : null)\n  .filter(t => t !== null)\n  .sort((a, b) => a - b);\n\nconst startTime = processedTimes.length > 0 ? processedTimes[0] : null;\nconst endTime = processedTimes.length > 0 ? processedTimes[processedTimes.length - 1] : null;\nconst durationSec = startTime && endTime ? ((endTime - startTime) / 1000).toFixed(1) : 0;\n\nconst accountStats = {};\nconst statusDetails = {\n  success: [],\n  crawled: [],\n  failed: []\n};\n\nconst successAccountsMap = new Map();\n\ninputData.forEach(json => {\n  const acc = json.account;\n  const status = json.status;\n  \n  if (!accountStats[acc]) {\n    accountStats[acc] = { \n      total: 0, \n      pureSuccess: 0, \n      crawled: 0, \n      failed: 0,\n      ids: {\n        pureSuccess: [],\n        crawled: [],\n        failed: []\n      }\n    };\n  }\n  \n  accountStats[acc].total++;\n  \n  const detailItem = {\n    account: acc,\n    id: json.id,\n    processedAt: json.processedAt,\n    checkedAt: json.account_checked_at,\n    reason: json.errorReason || ''\n  };\n  \n  if (status === 'success') {\n    accountStats[acc].pureSuccess++;\n    accountStats[acc].ids.pureSuccess.push(json.id);\n    statusDetails.success.push(detailItem);\n    \n    if (json.account_checked_at) {\n      successAccountsMap.set(acc, json.account_checked_at);\n    }\n  } else if (status === 'crawled') {\n    accountStats[acc].crawled++;\n    accountStats[acc].ids.crawled.push(json.id);\n    statusDetails.crawled.push(detailItem);\n    \n    if (json.account_checked_at) {\n      successAccountsMap.set(acc, json.account_checked_at);\n    }\n  } else if (status === 'failed') {\n    accountStats[acc].failed++;\n    accountStats[acc].ids.failed.push(json.id);\n    statusDetails.failed.push(detailItem);\n  }\n});\n\nlet report = `\ud83d\udcca Batch Task Processing Report\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\ud83d\udccc Overall Statistics\n   \ud83d\udc64 Accounts Involved: ${accountCount}\n   \ud83d\udce6 Total Tasks: ${totalCount}\n   \u2705 Pure Success: ${pureSuccessCount}\n   \ud83d\udd04 Already Crawled: ${crawledCount}\n   \ud83d\udcca Effective Success: ${effectiveSuccessCount}\n   \u274c Failed: ${failCount}\n   \ud83d\udcc8 Success Rate: ${successRate}%`;\n\nif (startTime && endTime) {\n  report += `\n   \u23f1\ufe0f  Processing Period: ${startTime.toISOString().replace('T', ' ').substring(0, 19)} ~ ${endTime.toISOString().replace('T', ' ').substring(0, 19)}\n   \u23f3 Total Duration: ${durationSec} seconds`;\n}\n\nreport += `\n\n\ud83d\udccb Per-Account Statistics (${accountCount} Accounts)`;\n\nconst accounts = Object.entries(accountStats);\naccounts.forEach(([account, stats], index) => {\n  const accRate = stats.total > 0 ? (((stats.pureSuccess + stats.crawled) / stats.total) * 100).toFixed(0) : 0;\n  const isLast = index === accounts.length - 1;\n  const prefix = isLast ? '\u2514\u2500' : '\u251c\u2500';\n  const childPrefix = isLast ? '   ' : '\u2502  ';\n  \n  report += `\n   ${prefix} Account: ${account}\n   ${childPrefix}\u251c\u2500 Total: ${stats.total}  (Success Rate: ${accRate}%)\n   ${childPrefix}\u251c\u2500 Pure Success: ${stats.pureSuccess} \n   ${childPrefix}\u251c\u2500 Already Crawled: ${stats.crawled} \n   ${childPrefix}\u2514\u2500 Failed: ${stats.failed} `;\n});\n\nif (statusDetails.success.length > 0) {\n  report += `\n\n\u2705 Pure Success Task Details (${statusDetails.success.length})`;\n  statusDetails.success.forEach((item, idx) => {\n    report += `\n   ${idx + 1}. Account: ${item.account} | ID: ${item.id}\n      \u2514\u2500 Processed At: ${item.processedAt || 'N/A'} | Checked At: ${item.checkedAt || 'N/A'}`;\n  });\n}\n\nif (statusDetails.crawled.length > 0) {\n  report += `\n\n\ud83d\udcdd Already Crawled Task Details (${statusDetails.crawled.length})`;\n  statusDetails.crawled.forEach((item, idx) => {\n    report += `\n   ${idx + 1}. Account: ${item.account} | ID: ${item.id}`;\n    if (item.reason) report += ` | Reason: ${item.reason}`;\n    report += `\n      \u2514\u2500 Processed At: ${item.processedAt || 'N/A'}`;\n  });\n}\n\nif (statusDetails.failed.length > 0) {\n  report += `\n\n\u26a0\ufe0f Failed Task Details (${statusDetails.failed.length} items)`;\n  statusDetails.failed.forEach((item, idx) => {\n    report += `\n   ${idx + 1}. Account: ${item.account} | ID: ${item.id}\n      \u251c\u2500 Reason: ${item.reason || 'Unknown Error'}\n      \u2514\u2500 Processed At: ${item.processedAt || 'N/A'}`;\n  });\n}\n\nconst needUpdates = Array.from(successAccountsMap.entries()).map(([account, checkedAt]) => ({ \n  account,\n  account_checked_at: checkedAt \n}));\n\nif (needUpdates.length > 0) {\n  report += `\n\n\ud83d\udd04 Accounts Needing Updates (${needUpdates.length} accounts)`;\n  needUpdates.forEach((item, idx) => {\n    report += `\n   ${idx + 1}. ${item.account} (Checked At: ${item.account_checked_at})`;\n  });\n}\n\nconst timeStr = $now.toUTC().toFormat(\"yyyy-MM-dd'T'HH:mm:ss'Z'\");\nreport += `\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\u23f0 Report Generated At: ${timeStr}`;\n\nreturn {\n    json: {\n      reportText: report,\n      summary: {\n        accountCount: accountCount, \n        uniqueAccounts: uniqueAccounts,\n        total: totalCount,\n        pureSuccess: pureSuccessCount,\n        crawled: crawledCount,\n        effectiveSuccess: effectiveSuccessCount,\n        failed: failCount,\n        successRate: successRate + '%',\n        timeRange: startTime && endTime ? {\n          start: startTime.toISOString(),\n          end: endTime.toISOString(),\n          durationSeconds: parseFloat(durationSec)\n        } : null\n      },\n      accountDetails: accountStats,\n      statusBreakdown: statusDetails,\n      needUpdates: needUpdates,\n      rawData: inputData\n    }\n};"
      },
      "executeOnce": false,
      "typeVersion": 2
    },
    {
      "id": "1cc701eb-1088-471e-9065-9143a4b5b26d",
      "name": "Send Run Summary to Telegram",
      "type": "n8n-nodes-base.telegram",
      "onError": "continueRegularOutput",
      "position": [
        3328,
        512
      ],
      "parameters": {
        "text": "={{ $json.reportText }}",
        "chatId": "123456789",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "retryOnFail": true,
      "typeVersion": 1.2
    },
    {
      "id": "be244c9b-d0f9-41ac-b8fe-ea6c9c037916",
      "name": "Filter Reels by Date",
      "type": "n8n-nodes-base.code",
      "position": [
        3232,
        1136
      ],
      "parameters": {
        "jsCode": "const now = new Date();\nconst oneDayMs = 24 * 60 * 60 * 1000;\n\nconst filteredItems = items.filter(item => {\n  const capturedAt = new Date(item.json.captured_at);\n  const diffMs = now - capturedAt;\n  \n  return diffMs <= oneDayMs;\n});\n\nreturn filteredItems;"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "77f89511-918d-42fc-8392-1ac7eb11e8a9",
      "name": "Merge Filtered Reel Data",
      "type": "n8n-nodes-base.merge",
      "position": [
        3456,
        1168
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3.2
    },
    {
      "id": "d4a597c4-f37e-4546-a55a-5f69e9e6df2b",
      "name": "Filter Already Processed Reels",
      "type": "n8n-nodes-base.code",
      "position": [
        4544,
        1168
      ],
      "parameters": {
        "jsCode": "const inputData = $input.all();\n\nconst jiedian2Ids = inputData[0].json.jiedian2 || [];\nconst idSet = new Set(jiedian2Ids);\n\nconst jiedian1Item = inputData[0].json.jiedian1;\n\nconst id = jiedian1Item.id;\n\nif (!idSet.has(id)) {\n  return [jiedian1Item];\n} else {\n  return [{\"reel_id\":id, \"status\": \"crawled\"}];\n}\n"
      },
      "typeVersion": 2
    },
    {
      "id": "8bc3850a-e960-4233-b217-ea90e74080b6",
      "name": "Loop Over Reels in Batches",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        4112,
        1936
      ],
      "parameters": {
        "options": {
          "reset": "={{ $prevNode.name === 'Merge New and Existing Reel Data' }}"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "b4d7bebe-beca-41d6-afbd-31c838c93b3b",
      "name": "Update Failed Reel in Library",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueRegularOutput",
      "position": [
        5680,
        1488
      ],
      "parameters": {
        "columns": {
          "value": {
            "reel_id": "={{ $('Upsert Reel in Sheets').item.json.reel_id }}",
            "row_number": 0,
            "error_message": "={{ $json.errorReason }}",
            "process_status": "SKIPPED"
          },
          "schema": [
            {
              "id": "reel_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "reel_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "reel_url",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "reel_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "instagram_username",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "instagram_username",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "account_name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "account_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "published_at",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "published_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "run_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "run_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "captured_at",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "captured_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "caption",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "caption",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "transcript",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "transcript",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "summary",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "main_topic",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "main_topic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hook",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "hook",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hook_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "hook_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CTA_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "CTA_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "content_angle",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "content_angle",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "reusable_idea",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "reusable_idea",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tags",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "tags",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "process_status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "process_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "error_message",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "error_message",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "reel_id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Reels Library"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Reset Temp Parameters').last().json.google_sheet_share_link }}"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.7
    },
    {
      "id": "4b7b8066-d8bd-4290-9b24-41de65d3610a",
      "name": "Append to Latest Run Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueRegularOutput",
      "position": [
        5904,
        1488
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "reel_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "reel_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "captured_at",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "captured_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "process_status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "process_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Current Run ID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Latest Run"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Reset Temp Parameters').last().json.google_sheet_share_link }}"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.7
    },
    {
      "id": "80a8a24d-f411-4ea1-8395-e5a60225ad8b",
      "name": "Get Accounts Needing Updates",
      "type": "n8n-nodes-base.code",
      "position": [
        3328,
        320
      ],
      "parameters": {
        "jsCode": "return  $input.first().json.needUpdates || [];"
      },
      "typeVersion": 2
    },
    {
      "id": "7fae8424-d47b-44ed-a936-69c2f0bddf5a",
      "name": "Deduplicate Aggregated Data",
      "type": "n8n-nodes-base.code",
      "position": [
        2928,
        416
      ],
      "parameters": {
        "jsCode": "const inputData = items[0].json.data || [];\n\nconst filteredItems = inputData.filter(item => {\n  return item.source === \"processed_result\";\n});\n\nconst uniqueMap = new Map();\nfor (const item of filteredItems) {\n  const key = item.id || `${item.account}_${item.processedAt}`;\n  if (!uniqueMap.has(key)) {\n    uniqueMap.set(key, item);\n  }\n}\n\nconst result = Array.from(uniqueMap.values()).map(item => ({\n  json: item\n}));\n\nreturn result;"
      },
      "typeVersion": 2
    },
    {
      "id": "96cfaa98-0f16-4689-ae73-615eb0ea11fe",
      "name": "Aggregate Account Results",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        2688,
        416
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "executeOnce": false,
      "typeVersion": 1
    },
    {
      "id": "00244598-0168-445f-80a7-2df95c19d12e",
      "name": "Filter Video Reels",
      "type": "n8n-nodes-base.filter",
      "position": [
        2720,
        1328
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "596604aa-3685-41ab-bcc1-6d76e501f355",
              "operator": {
                "type": "number",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.pk }}",
              "rightValue": ""
            },
            {
              "id": "3e909b33-7fe8-48f2-858c-6e21ad895989",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.type }}",
              "rightValue": "Video"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.3,
      "alwaysOutputData": false
    },
    {
      "id": "1ff45ea9-3d4f-4298-9686-d78c87d6cd2b",
      "name": "If Scrape Returned Results",
      "type": "n8n-nodes-base.if",
      "position": [
        2976,
        848
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "30823821-74a3-4ac9-afe5-265a063e034d",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $input.all().length < 1 }}",
              "rightValue": ""
            },
            {
              "id": "f3dc7693-77cd-4bb8-8e5b-f4310daf510a",
              "operator": {
                "type": "string",
                "operation": "notExists",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": "\"\""
            },
            {
              "id": "90552e82-55d5-4091-805f-e8ad590f034d",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.error }}",
              "rightValue": "no_items"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "11576497-d46a-4ebe-b2a3-74b4333d57a1",
      "name": "Read Existing Reels from Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueRegularOutput",
      "position": [
        2992,
        1168
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.id }}",
              "lookupColumn": "reel_id"
            },
            {
              "lookupValue": "DONE",
              "lookupColumn": "process_status"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Latest Run"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Set Global Workflow Settings').item.json.google_sheet_share_link }}"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "a80c93d4-9ef2-444a-8f80-eb0d33d05b1a",
      "name": "Format Lock Warning Message",
      "type": "n8n-nodes-base.code",
      "position": [
        1856,
        -128
      ],
      "parameters": {
        "jsCode": "const workflowStaticData = $getWorkflowStaticData('global');\ndelete workflowStaticData.isRunning;\ndelete workflowStaticData.startTime;\ndelete workflowStaticData.executionId;\nreturn [{ json: { message: $input.first().json.reason } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "7b735784-dfdd-4bb6-9a24-6b272493ef11",
      "name": "Set No Transcript Error",
      "type": "n8n-nodes-base.set",
      "position": [
        5392,
        1488
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "311e9e65-fd04-4dfb-b41a-d172a518a5c6",
              "name": "=errorReason",
              "type": "string",
              "value": "={{ $json.errMsg || 'Transcript is empty or too short'}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6e38552c-8f2d-4442-83a1-d97fea1e4fc0",
      "name": "Set No Transcript Status",
      "type": "n8n-nodes-base.set",
      "position": [
        6128,
        1488
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d19fcca9-b5f5-4172-8403-8b41ba7a6ede",
              "name": "account",
              "type": "string",
              "value": "={{ $('Reset Temp Parameters').last().json.instagram_username }}"
            },
            {
              "id": "8b309609-7278-4c9b-9409-fc322734c66e",
              "name": "status",
              "type": "string",
              "value": "failed"
            },
            {
              "id": "9d695e91-37ab-4715-b3a8-af556c9d1531",
              "name": "errorReason",
              "type": "string",
              "value": "={{ $('Update Failed Reel in Library').item.json.error_message || $json.error}}"
            },
            {
              "id": "9b3acdf4-3aa7-485f-b127-0c854dbb2ed8",
              "name": "processedAt",
              "type": "string",
              "value": "={{ $now }}"
            },
            {
              "id": "6524039f-1ad3-4161-9188-7de312504291",
              "name": "account_checked_at",
              "type": "string",
              "value": "={{ $('Reset Temp Parameters').last().json.account_checked_at }}"
            },
            {
              "id": "31ef5ac0-0219-4261-92ec-de71115fd3ca",
              "name": "source",
              "type": "string",
              "value": "processed_result"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "b6ccd653-c5c4-4364-9f92-73a025bca26b",
      "name": "Set Skipped Info Status",
      "type": "n8n-nodes-base.set",
      "position": [
        6496,
        1152
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ea389a65-549f-4691-b9bb-861e83ea1819",
              "name": "account",
              "type": "string",
              "value": "={{ $('Reset Temp Parameters').last().json.instagram_username }}"
            },
            {
              "id": "bc963c40-0ee9-4b12-9223-ea8d17cab20b",
              "name": "id",
              "type": "string",
              "value": "={{ $json.reel_id }}"
            },
            {
              "id": "968bf511-0f2d-48b1-9212-00628f763447",
              "name": "status",
              "type": "string",
              "value": "crawled"
            },
            {
              "id": "b6fbd5c1-c5cf-45d9-b700-3a5a376a8ccd",
              "name": "errorReason",
              "type": "string",
              "value": "Has already been crawled."
            },
            {
              "id": "efa51c15-8625-4239-8509-c6a731ad4662",
              "name": "processedAt",
              "type": "string",
              "value": "={{ $now }}"
            },
            {
              "id": "9f161bd6-79d4-4e6a-b40c-ea0f39daf251",
              "name": "account_checked_at",
              "type": "string",
              "value": "={{ $('Reset Temp Parameters').last().json.account_checked_at }}"
            },
            {
              "id": "3ce35886-7b10-4179-b63d-b27d8adfc502",
              "name": "source",
              "type": "string",
              "value": "processed_result"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c85933c8-811f-4c36-b24c-e500fb82fa82",
      "name": "Set Scrape Failed Status",
      "type": "n8n-nodes-base.set",
      "position": [
        4304,
        832
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ea389a65-549f-4691-b9bb-861e83ea1819",
              "name": "account",
              "type": "string",
              "value": "={{ $('Loop Over Active Accounts').item.json.instagram_username }}"
            },
            {
              "id": "bc963c40-0ee9-4b12-9223-ea8d17cab20b",
              "name": "id",
              "type": "string",
              "value": "={{ $json.id }}"
            },
            {
              "id": "968bf511-0f2d-48b1-9212-00628f763447",
              "name": "status",
              "type": "string",
              "value": "failed"
            },
            {
              "id": "b6fbd5c1-c5cf-45d9-b700-3a5a376a8ccd",
              "name": "errorReason",
              "type": "string",
              "value": "={{ $json.error || 'no data from search reels from apify'}}"
            },
            {
              "id": "efa51c15-8625-4239-8509-c6a731ad4662",
              "name": "processedAt",
              "type": "string",
              "value": "={{ $now }}"
            },
            {
              "id": "cdaa14d2-23ad-466b-aa73-112143929f75",
              "name": "account_checked_at",
              "type": "string",
              "value": ""
            },
            {
              "id": "51954e04-0954-4c8b-98c5-6d8303e44460",
              "name": "source",
              "type": "string",
              "value": "processed_result"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c3e0ef75-dbb4-40ca-8fc6-7e423279c77f",
      "name": "Set Success Status",
      "type": "n8n-nodes-base.set",
      "position": [
        6128,
        1824
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "3823dd02-15d9-4174-b9ba-0d2046e0233f",
              "name": "account",
              "type": "string",
              "value": "={{ $('Reset Temp Parameters').last().json.instagram_username }}"
            },
            {
              "id": "77bdaad1-7379-4154-a900-c2850a089d9b",
              "name": "status",
              "type": "string",
              "value": "success"
            },
            {
              "id": "75bc568f-45fe-4b68-b093-b48276a1e0b7",
              "name": "errorReason",
              "type": "string",
              "value": ""
            },
            {
              "id": "8a1a44be-7094-4500-b652-7e528740ff0a",
              "name": "processedAt",
              "type": "string",
              "value": "={{ $now }}"
            },
            {
              "id": "f3313df4-a22a-47f0-9544-63e48f7a9edc",
              "name": "id",
              "type": "string",
              "value": "={{ $('Update Successful Reel in Sheet').item.json.reel_id }}"
            },
            {
              "id": "9d8b2e7b-0b33-4bda-94da-4f652328c68c",
              "name": "account_checked_at",
              "type": "string",
              "value": "={{ $json.captured_at }}"
            },
            {
              "id": "8609dfd1-4d5a-41a4-a863-9b819776baa9",
              "name": "source",
              "type": "string",
              "value": "processed_result"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "15ef5a08-a993-4876-be3d-1d3e45dc387f",
      "name": "Append Successful Reel to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        5904,
        1824
      ],
      "parameters": {
        "columns": {
          "value": {
            "reel_id": "={{ $json.reel_id }}",
            "captured_at": "={{ $('Upsert Reel in Sheets').item.json.captured_at }}",
            "process_status": "DONE"
          },
          "schema": [
            {
              "id": "reel_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "reel_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "captured_at",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "captured_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "process_status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "process_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Current Run ID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Latest Run"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Reset Temp Parameters').last().json.google_sheet_share_link }}"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.7
    },
    {
      "id": "5556acfe-4c78-49df-af85-8d3ec4bcb95f",
      "name": "Update Successful Reel in Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        5680,
        1824
      ],
      "parameters": {
        "columns": {
          "value": {
            "hook": "={{ $json.output[0].content[0].text.hook }}",
            "tags": "={{ $json.output[0].content[0].text.tags }}",
            "caption": "={{ $('Upsert Reel in Sheets').item.json.caption }}",
            "reel_id": "={{ $('Upsert Reel in Sheets').item.json.reel_id }}",
            "summary": "={{ $json.output[0].content[0].text.summary }}",
            "CTA_type": "={{ $json.output[0].content[0].text.CTA_type }}",
            "hook_type": "={{ $json.output[0].content[0].text.hook_type }}",
            "main_topic": "={{ $json.output[0].content[0].text.main_topic }}",
            "row_number": 0,
            "transcript": "={{ $('Generate Transcript with Apify').item.json.text }}",
            "content_angle": "={{ $json.output[0].content[0].text.content_angle }}",
            "reusable_idea": "={{ $json.output[0].content[0].text.reusable_idea }}",
            "process_status": "DONE"
          },
          "schema": [
            {
              "id": "reel_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "reel_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "reel_url",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "reel_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "instagram_username",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "instagram_username",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "account_name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "account_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "published_at",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "published_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "run_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "run_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "captured_at",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "captured_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "caption",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "caption",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "transcript",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "transcript",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "summary",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "main_topic",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "main_topic",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hook",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "hook",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "hook_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "hook_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CTA_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "CTA_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "content_angle",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "content_angle",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "reusable_idea",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "reusable_idea",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tags",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "tags",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "process_status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "process_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "error_message",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "error_message",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "reel_id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Reels Library"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $('Reset Temp Parameters').last().json.google_sheet_share_link }}"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.7
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "812155e1-e0bb-40c9-80ab-3fca9e192bc4",
  "connections": {
    "Wait 1 Second": {
      "main": [
        [
          {
            "node": "Loop Over Reels in Batches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 2 Seconds": {
      "main": [
        [
          {
            "node": "Loop Over Active Accounts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every Hour Trigger": {
      "main": [
        [
          {
            "node": "Acquire Run Lock Flag",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Video Reels": {
      "main": [
        [
          {
            "node": "Read Existing Reels from Sheets",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge Filtered Reel Data",
            "type": "main",
            "index": 1
          },
          {
            "node": "Prepare Reel Parameters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Success Status": {
      "main": [
        [
          {
            "node": "Wait 1 Second",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Reels by Date": {
      "main": [
        [
          {
            "node": "Merge Filtered Reel Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Acquire Run Lock Flag": {
      "main": [
        [
          {
            "node": "If Workflow Already Running",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Reset Temp Parameters": {
      "main": [
        [
          {
            "node": "Merge New and Existing Reel Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert Reel in Sheets": {
      "main": [
        [
          {
            "node": "Generate Transcript with Apify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Transcript Available": {
      "main": [
        [
          {
            "node": "Set No Transcript Error",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "OpenAI Reel Content Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Reel Parameters": {
      "main": [
        [
          {
            "node": "Merge Filtered Reel Data",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Set No Transcript Error": {
      "main": [
        [
          {
            "node": "Update Failed Reel in Library",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Skipped Info Status": {
      "main": [
        [
          {
            "node": "Wait 1 Second",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Run Summary Report": {
      "main": [
        [
          {
            "node": "Get Accounts Needing Updates",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send Run Summary to Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Filtered Reel Data": {
      "main": [
        [
          {
            "node": "Reset Temp Parameters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set No Transcript Status": {
      "main": [
        [
          {
            "node": "Wait 1 Second",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Scrape Failed Status": {
      "main": [
        [
          {
            "node": "Wait 2 Seconds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Account Results": {
      "main": [
        [
          {
            "node": "Deduplicate Aggregated Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Active Accounts": {
      "main": [
        [
          {
            "node": "Aggregate Account Results",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Scrape Recent Reels with Apify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Accounts from Sheets": {
      "main": [
        [
          {
            "node": "Set Account Filter Values",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Account Filter Values": {
      "main": [
        [
          {
            "node": "Filter Accounts by Check Window",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append to Latest Run Sheet": {
      "main": [
        [
          {
            "node": "Set No Transcript Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format No Accounts Message": {
      "main": [
        [
          {
            "node": "Send Workflow Status to Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Scrape Returned Results": {
      "main": [
        [
          {
            "node": "Set Scrape Failed Status",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Filter Video Reels",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Reels in Batches": {
      "main": [
        [
          {
            "node": "Wait 2 Seconds",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Filter Already Processed Reels",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Reel Exists in Sheets": {
      "main": [
        [
          {
            "node": "Set Skipped Info Status",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Upsert Reel in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Deduplicate Aggregated Data": {
      "main": [
        [
          {
            "node": "Build Run Summary Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Lock Warning Message": {
      "main": [
        [
          {
            "node": "Send Workflow Status to Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Checkable Accounts Exist": {
      "main": [
        [
          {
            "node": "Format No Accounts Message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Active Accounts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Workflow Already Running": {
      "main": [
        [
          {
            "node": "Format Lock Warning Message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set Global Workflow Settings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Accounts Needing Updates": {
      "main": [
        [
          {
            "node": "Update Account Check Timestamp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Reel Content Analysis": {
      "main": [
        [
          {
            "node": "Update Successful Reel in Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Global Workflow Settings": {
      "main": [
        [
          {
            "node": "Read Accounts from Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Failed Reel in Library": {
      "main": [
        [
          {
            "node": "Append to Latest Run Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Already Processed Reels": {
      "main": [
        [
          {
            "node": "Check Reel Exists in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Transcript with Apify": {
      "main": [
        [
          {
            "node": "If Transcript Available",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Recent Reels with Apify": {
      "main": [
        [
          {
            "node": "If Scrape Returned Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append Successful Reel to Sheet": {
      "main": [
        [
          {
            "node": "Set Success Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Accounts by Check Window": {
      "main": [
        [
          {
            "node": "If Checkable Accounts Exist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Existing Reels from Sheets": {
      "main": [
        [
          {
            "node": "Filter Reels by Date",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Successful Reel in Sheet": {
      "main": [
        [
          {
            "node": "Append Successful Reel to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge New and Existing Reel Data": {
      "main": [
        [
          {
            "node": "Loop Over Reels in Batches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}