{
  "name": "Daily Social Media Auto-Post from Google Sheets",
  "nodes": [
    {
      "id": "sticky-0001",
      "name": "Setup Instructions",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        240,
        60
      ],
      "parameters": {
        "content": "## Daily Social Media Auto-Post\n\n**Posts every day at 6:00 AM — all ready platforms at once**\n\n**Sheet columns (exact names):**\nContent | Platform | ScheduledDate | Status | VideoURL | ImageURL | Hashtags | Title | Notes | PostID | PostedAt\n\n**Platform values:** LinkedIn, Instagram, Twitter, YouTube, TikTok\n**ScheduledDate format:** YYYY-MM-DD\n**Status flow:** (blank) → ready → posted\n\n**Video platforms:** YouTube and TikTok require VideoURL to be a direct, publicly accessible video URL\n\n**Credentials to create in n8n:**\n- Google Sheets: Service Account (googleApi)\n- LinkedIn: no credential (token refreshed inline)\n- Instagram: HTTP Header Auth (httpHeaderAuth)\n- Twitter: Twitter OAuth2 (twitterOAuth2Api)\n- YouTube: YouTube OAuth2 API (youTubeOAuth2Api) — set up via localhost:5678 not Tailscale IP\n- TikTok: Generic OAuth2 (oAuth2Api) — see TikTok setup guide\n\n**Google Sheets nodes are pre-configured to social-media-posts / Sheet1**\nIf the credential ID doesn't match, open each Google Sheets node and reselect your credential.",
        "height": 440,
        "width": 660,
        "color": 6
      }
    },
    {
      "id": "a1b2c3d4-0001-0001-0001-000000000001",
      "name": "Every Day at 6am",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        620
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 6 * * *"
            }
          ]
        }
      }
    },
    {
      "id": "a1b2c3d4-0002-0002-0002-000000000002",
      "name": "Read Sheet Rows",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.2,
      "position": [
        460,
        620
      ],
      "parameters": {
        "operation": "getAll",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "list",
          "cachedResultName": "social-media-posts",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_SPREADSHEET_ID/edit"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1"
        },
        "returnAll": true,
        "filtersUI": {},
        "options": {}
      }
    },
    {
      "id": "a1b2c3d4-0003-0003-0003-000000000003",
      "name": "Filter by Status",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        620
      ],
      "parameters": {
        "jsCode": "return $input.all().filter(item => {\n  return (item.json.Status || '').toString().trim().toLowerCase() === 'ready';\n});"
      }
    },
    {
      "id": "a1b2c3d4-0003b-003b-003b-00000000003c",
      "name": "Filter by Date",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        840,
        620
      ],
      "parameters": {
        "jsCode": "const today = new Date().toISOString().split('T')[0];\n\nreturn $input.all().filter(item => {\n  const val = item.json.ScheduledDate;\n  if (!val && val !== 0) return false;\n\n  if (typeof val === 'number') {\n    const epoch = new Date(1899, 11, 30);\n    const d = new Date(epoch.getTime() + val * 86400000);\n    return d.toISOString().split('T')[0] === today;\n  }\n\n  const str = val.toString().trim();\n  if (/^\\d{4}-\\d{2}-\\d{2}$/.test(str)) return str === today;\n\n  const d = new Date(str);\n  if (!isNaN(d.getTime())) return d.toISOString().split('T')[0] === today;\n\n  return false;\n});"
      }
    },
    {
      "id": "a1b2c3d4-0004-0004-0004-000000000004",
      "name": "Route by Platform",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3,
      "position": [
        1000,
        620
      ],
      "parameters": {
        "mode": "rules",
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "id": "rule-linkedin",
                    "leftValue": "={{ $json.Platform }}",
                    "rightValue": "LinkedIn",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "LinkedIn"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "id": "rule-instagram",
                    "leftValue": "={{ $json.Platform }}",
                    "rightValue": "Instagram",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Instagram"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "id": "rule-twitter",
                    "leftValue": "={{ $json.Platform }}",
                    "rightValue": "Twitter",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Twitter"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "id": "rule-youtube",
                    "leftValue": "={{ $json.Platform }}",
                    "rightValue": "YouTube",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "YouTube"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": false,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "id": "rule-tiktok",
                    "leftValue": "={{ $json.Platform }}",
                    "rightValue": "TikTok",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "TikTok"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "a1b2c3d4-0004b-004b-004b-00000000004b",
      "name": "Refresh LinkedIn Token",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        1220,
        160
      ],
      "parameters": {
        "method": "POST",
        "url": "https://www.linkedin.com/oauth/v2/accessToken",
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "grant_type",
              "value": "refresh_token"
            },
            {
              "name": "refresh_token",
              "value": "YOUR_LINKEDIN_REFRESH_TOKEN"
            },
            {
              "name": "client_id",
              "value": "YOUR_LINKEDIN_CLIENT_ID"
            },
            {
              "name": "client_secret",
              "value": "YOUR_LINKEDIN_CLIENT_SECRET"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "a1b2c3d4-0005-0005-0005-000000000005",
      "name": "Post to LinkedIn",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        1440,
        160
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.linkedin.com/v2/ugcPosts",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $json.access_token }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "X-Restli-Protocol-Version",
              "value": "2.0.0"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ author: 'urn:li:person:YOUR_PERSON_URN', lifecycleState: 'PUBLISHED', specificContent: { 'com.linkedin.ugc.ShareContent': { shareCommentary: { text: $('Route by Platform').item.json.Content + ($('Route by Platform').item.json.Hashtags ? '\\n\\n' + $('Route by Platform').item.json.Hashtags : '') }, shareMediaCategory: 'NONE' } }, visibility: { 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC' } }) }}",
        "options": {}
      }
    },
    {
      "id": "a1b2c3d4-0009-0009-0009-000000000009",
      "name": "Update Sheet — LinkedIn",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.2,
      "position": [
        1660,
        160
      ],
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "list",
          "cachedResultName": "social-media-posts",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_SPREADSHEET_ID/edit"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "row_number": "={{ $('Read Sheet Rows').item.json.row_number }}",
            "Status": "posted",
            "PostID": "={{ $json.id }}",
            "PostedAt": "={{ $now.toISO() }}"
          },
          "matchingColumns": [
            "row_number"
          ],
          "schema": []
        },
        "options": {}
      }
    },
    {
      "id": "a1b2c3d4-0006-0006-0006-000000000006",
      "name": "Instagram — Create Container",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1220,
        400
      ],
      "parameters": {
        "method": "POST",
        "url": "=https://graph.facebook.com/v18.0/YOUR_IG_USER_ID/media",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "caption",
              "value": "={{ $json.Content + ($json.Hashtags ? '\\n\\n' + $json.Hashtags : '') }}"
            },
            {
              "name": "image_url",
              "value": "={{ $json.ImageURL }}"
            },
            {
              "name": "media_type",
              "value": "IMAGE"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "a1b2c3d4-0007-0007-0007-000000000007",
      "name": "Instagram — Publish Media",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1440,
        400
      ],
      "parameters": {
        "method": "POST",
        "url": "=https://graph.facebook.com/v18.0/YOUR_IG_USER_ID/media_publish",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "creation_id",
              "value": "={{ $json.id }}"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "a1b2c3d4-0010-0010-0010-000000000010",
      "name": "Update Sheet — Instagram",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.2,
      "position": [
        1660,
        400
      ],
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "list",
          "cachedResultName": "social-media-posts",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_SPREADSHEET_ID/edit"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "row_number": "={{ $('Read Sheet Rows').item.json.row_number }}",
            "Status": "posted",
            "PostID": "={{ $json.id }}",
            "PostedAt": "={{ $now.toISO() }}"
          },
          "matchingColumns": [
            "row_number"
          ],
          "schema": []
        },
        "options": {}
      }
    },
    {
      "id": "a1b2c3d4-0008-0008-0008-000000000008",
      "name": "Post to Twitter / X",
      "type": "n8n-nodes-base.twitter",
      "typeVersion": 2,
      "position": [
        1220,
        640
      ],
      "parameters": {
        "resource": "tweet",
        "operation": "create",
        "text": "={{ $json.Content }}",
        "additionalFields": {}
      }
    },
    {
      "id": "a1b2c3d4-0011-0011-0011-000000000011",
      "name": "Update Sheet — Twitter",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.2,
      "position": [
        1440,
        640
      ],
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "list",
          "cachedResultName": "social-media-posts",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_SPREADSHEET_ID/edit"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "row_number": "={{ $('Read Sheet Rows').item.json.row_number }}",
            "Status": "posted",
            "PostID": "={{ $json.data.id }}",
            "PostedAt": "={{ $now.toISO() }}"
          },
          "matchingColumns": [
            "row_number"
          ],
          "schema": []
        },
        "options": {}
      }
    },
    {
      "id": "yt-fetch-0001",
      "name": "Fetch Video for YouTube",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        1220,
        880
      ],
      "parameters": {
        "method": "GET",
        "url": "={{ $json.VideoURL }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      }
    },
    {
      "id": "yt-upload-0001",
      "name": "Upload to YouTube",
      "type": "n8n-nodes-base.youTube",
      "typeVersion": 1,
      "position": [
        1440,
        880
      ],
      "parameters": {
        "resource": "video",
        "operation": "upload",
        "title": "={{ $('Route by Platform').item.json.Title || $('Route by Platform').item.json.Content.substring(0, 100) }}",
        "categoryId": "28",
        "binaryProperty": "data",
        "options": {
          "description": "={{ $('Route by Platform').item.json.Content + ($('Route by Platform').item.json.Hashtags ? '\\n\\n' + $('Route by Platform').item.json.Hashtags : '') + '\\n\\n#Shorts' }}",
          "privacyStatus": "public"
        }
      }
    },
    {
      "id": "yt-update-0001",
      "name": "Update Sheet — YouTube",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.2,
      "position": [
        1660,
        880
      ],
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "list",
          "cachedResultName": "social-media-posts",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_SPREADSHEET_ID/edit"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "row_number": "={{ $('Read Sheet Rows').item.json.row_number }}",
            "Status": "posted",
            "PostID": "={{ $json.id }}",
            "PostedAt": "={{ $now.toISO() }}"
          },
          "matchingColumns": [
            "row_number"
          ],
          "schema": []
        },
        "options": {}
      }
    },
    {
      "id": "tt-post-0001",
      "name": "Post to TikTok",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        1220,
        1120
      ],
      "parameters": {
        "method": "POST",
        "url": "https://open.tiktokapis.com/v2/post/publish/video/init/",
        "authentication": "genericCredentialType",
        "genericAuthType": "oAuth2Api",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ post_info: { title: ($json.Title || $json.Content).substring(0, 150), privacy_level: 'PUBLIC_TO_EVERYONE', disable_duet: false, disable_comment: false, disable_stitch: false }, source_info: { source: 'PULL_FROM_URL', video_url: $json.VideoURL } }) }}",
        "options": {}
      }
    },
    {
      "id": "tt-update-0001",
      "name": "Update Sheet — TikTok",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.2,
      "position": [
        1440,
        1120
      ],
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "list",
          "cachedResultName": "social-media-posts",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_SPREADSHEET_ID/edit"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "row_number": "={{ $('Read Sheet Rows').item.json.row_number }}",
            "Status": "posted",
            "PostID": "={{ $json.data.publish_id }}",
            "PostedAt": "={{ $now.toISO() }}"
          },
          "matchingColumns": [
            "row_number"
          ],
          "schema": []
        },
        "options": {}
      }
    }
  ],
  "connections": {
    "Every Day at 6am": {
      "main": [
        [
          {
            "node": "Read Sheet Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Sheet Rows": {
      "main": [
        [
          {
            "node": "Filter by Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter by Status": {
      "main": [
        [
          {
            "node": "Filter by Date",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter by Date": {
      "main": [
        [
          {
            "node": "Route by Platform",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Platform": {
      "main": [
        [
          {
            "node": "Refresh LinkedIn Token",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Instagram — Create Container",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Post to Twitter / X",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Fetch Video for YouTube",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Post to TikTok",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Refresh LinkedIn Token": {
      "main": [
        [
          {
            "node": "Post to LinkedIn",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to LinkedIn": {
      "main": [
        [
          {
            "node": "Update Sheet — LinkedIn",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Instagram — Create Container": {
      "main": [
        [
          {
            "node": "Instagram — Publish Media",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Instagram — Publish Media": {
      "main": [
        [
          {
            "node": "Update Sheet — Instagram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Twitter / X": {
      "main": [
        [
          {
            "node": "Update Sheet — Twitter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Video for YouTube": {
      "main": [
        [
          {
            "node": "Upload to YouTube",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to YouTube": {
      "main": [
        [
          {
            "node": "Update Sheet — YouTube",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to TikTok": {
      "main": [
        [
          {
            "node": "Update Sheet — TikTok",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}
