{
  "id": "nRMwWJXXDVubntEH",
  "name": "Auto-Post to Instagram, Facebook & LinkedIn from a Google Sheet",
  "tags": [],
  "nodes": [
    {
      "id": "a1111111-1111-4111-8111-111111111111",
      "name": "Sticky Note - Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        80,
        280
      ],
      "parameters": {
        "color": 7,
        "width": 500,
        "height": 640,
        "content": "## \ud83d\udcc5 Social Calendar \u2192 Instagram, Facebook & LinkedIn\n\nReads a Google Sheets content calendar once a day and auto-publishes each scheduled post (image or Reel) to Instagram and Facebook via the Meta Graph API, posts the same content to LinkedIn, then writes the result back to the sheet.\n\n### \u2699\ufe0f Setup \u2014 replace these placeholders\n- **Google Sheets:** connect your OAuth2 credential + set `YOUR_GOOGLE_SHEET_ID`\n- **Meta (IG + FB):** set `YOUR_IG_ACCOUNT_ID`, `YOUR_FB_PAGE_ID`, `YOUR_META_ACCESS_TOKEN`, `YOUR_FB_PAGE_ACCESS_TOKEN`\n- **LinkedIn:** connect OAuth2 + set `YOUR_LINKEDIN_PERSON_ID`\n- **(Optional) Cloudinary overlay:** set `YOUR_CLOUDINARY_CLOUD` + your logo/text\n\n### \ud83d\uddc2\ufe0f Required sheet columns\n`scheduled_date`, `status` (pending/posted/failed), `format` (image/reel), `image_source_url`, `caption_fr`, `hashtags`, unique `post_id`\n\nBuilt by WivoAgency \u2014 https://www.wivoagency.com"
      },
      "typeVersion": 1
    },
    {
      "id": "a2222222-2222-4222-8222-222222222222",
      "name": "Sticky Note - Step 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        620,
        180
      ],
      "parameters": {
        "color": 4,
        "width": 560,
        "height": 120,
        "content": "## 1) Read & filter the calendar\nRuns daily at 19:00 (Africa/Casablanca). Reads the `Content_Calendar` sheet and keeps only rows where `status = pending` and `scheduled_date = today`."
      },
      "typeVersion": 1
    },
    {
      "id": "a3333333-3333-4333-8333-333333333333",
      "name": "Sticky Note - Step 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1400,
        180
      ],
      "parameters": {
        "color": 4,
        "width": 380,
        "height": 120,
        "content": "## 2) Build the post\nCombines caption + hashtags, detects image vs Reel, and (optionally) builds a Cloudinary image URL with your logo/text overlay."
      },
      "typeVersion": 1
    },
    {
      "id": "a4444444-4444-4444-8444-444444444444",
      "name": "Sticky Note - Step 3 (Image)",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1840,
        150
      ],
      "parameters": {
        "color": 4,
        "width": 1080,
        "height": 110,
        "content": "## 3) Image path \u2192 Instagram, Facebook & LinkedIn\nCreates & publishes an Instagram image, posts the same image to your Facebook Page, then downloads it and publishes the post to LinkedIn."
      },
      "typeVersion": 1
    },
    {
      "id": "a5555555-5555-4555-8555-555555555555",
      "name": "Sticky Note - Step 4 (Reel)",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1840,
        620
      ],
      "parameters": {
        "color": 4,
        "width": 1100,
        "height": 110,
        "content": "## 4) Reel path \u2192 Instagram & Facebook\nCreates an Instagram Reel container, waits for processing, publishes it, then uploads the video to your Facebook Page."
      },
      "typeVersion": 1
    },
    {
      "id": "a6666666-6666-4666-8666-666666666666",
      "name": "Sticky Note - Step 5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3060,
        150
      ],
      "parameters": {
        "color": 4,
        "width": 380,
        "height": 120,
        "content": "## 5) Write back the result\nMarks the row `posted` with timestamp/IDs on success, or `failed` with the error message if a request fails."
      },
      "typeVersion": 1
    },
    {
      "id": "cc3019c2-a92b-4306-beeb-780694cb1a0d",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        672,
        368
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 19
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "d9ab0b1c-da68-42fb-87eb-bc2f713ec605",
      "name": "Read Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        880,
        368
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1301948859,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=1301948859",
          "cachedResultName": "Content_Calendar"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "6bc16abe-219e-45bf-b9fb-d4004c784702",
      "name": "Filter Today's Pending",
      "type": "n8n-nodes-base.code",
      "position": [
        1072,
        368
      ],
      "parameters": {
        "jsCode": "const now = new Date();\nconst casablancaDate = new Date(now.toLocaleString('en-US', { timeZone: 'Africa/Casablanca' }));\nconst yyyy = casablancaDate.getFullYear();\nconst mm = String(casablancaDate.getMonth() + 1).padStart(2, '0');\nconst dd = String(casablancaDate.getDate()).padStart(2, '0');\nconst todayStr = `${yyyy}-${mm}-${dd}`;\nconst items = $input.all();\nconst filtered = items.filter(item => {\n  const status = (item.json.status || '').toLowerCase().trim();\n  let schedDate = item.json.scheduled_date || '';\n  if (schedDate instanceof Date) {\n    schedDate = schedDate.toISOString().split('T')[0];\n  } else {\n    schedDate = String(schedDate).split('T')[0].trim();\n  }\n  return status === 'pending' && schedDate === todayStr;\n});\n\nreturn filtered;"
      },
      "typeVersion": 2
    },
    {
      "id": "21928b86-22f3-4675-87d4-e46dc2ab9b74",
      "name": "Prepare Post Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1472,
        368
      ],
      "parameters": {
        "jsCode": "const postData = $('Filter Today\\'s Pending').first().json;\n\nconst cloudName = 'YOUR_CLOUDINARY_CLOUD';\nconst format = (postData.format || 'image').toLowerCase().trim();\nconst sourceUrl = postData.image_source_url || '';\n\nlet mediaUrl = sourceUrl;\nlet mediaType = 'IMAGE';\n\nif (format === 'image') {\n  // For images: apply Cloudinary transformations with logo overlay\n  if (sourceUrl.includes('cloudinary.com')) {\n    const urlParts = sourceUrl.split('/upload/');\n    let publicId = urlParts[1] || '';\n    publicId = publicId.replace(/^v\\d+\\//, '');\n    publicId = publicId.replace(/\\.[^/.]+$/, '');\n    mediaUrl = `https://res.cloudinary.com/${cloudName}/image/upload/f_auto,q_auto,c_fill,ar_1:1,w_1080,h_1080/l_your-logo,w_150,g_north_west,x_30,y_30/l_text:Arial_22_italic:Your...Brand...Slogan,co_rgb:D4AF37,g_south,y_25/${publicId}.jpg`;\n  }\n  mediaType = 'IMAGE';\n} else if (format === 'reel') {\n  // For reels: use video URL directly (no transformation)\n  mediaUrl = sourceUrl;\n  mediaType = 'REELS';\n}\n\n// Combine caption and hashtags (matching original sheet structure)\nconst caption = postData.caption_fr || '';\nconst hashtags = postData.hashtags || '';\nconst fullCaption = hashtags ? `${caption}\\n\\n${hashtags}` : caption;\n\nreturn {\n  json: {\n    media_url: mediaUrl,\n    media_type: mediaType,\n    caption: fullCaption,\n    post_id: postData.post_id,\n    post_type: postData.post_type || 'vehicle',\n    format: format,\n    event_name: postData.event_name || '',\n    row_number: postData.row_number || ''\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "a2de627d-c386-4739-90c6-156b69cbe9ef",
      "name": "Switch Format",
      "type": "n8n-nodes-base.switch",
      "position": [
        1680,
        368
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "de4607d5-f31c-4f80-86e6-14045979c326",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.format }}",
                    "rightValue": "image"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "445e1828-5414-46dd-a9c2-3c66ca9aedca",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.format }}",
                    "rightValue": "reel"
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "b00e663c-dcae-4195-aba8-ae6681bc7755",
      "name": "Create IG Image Container",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1872,
        304
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v19.0/YOUR_IG_ACCOUNT_ID/media",
        "method": "POST",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "image_url",
              "value": "={{ $json.media_url }}"
            },
            {
              "name": "caption",
              "value": "={{ $json.caption }}"
            },
            {
              "name": "access_token",
              "value": "YOUR_META_ACCESS_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "890bdc09-0222-4c21-bbfc-01d3b3c214dc",
      "name": "Wait 15s - Image",
      "type": "n8n-nodes-base.wait",
      "position": [
        2080,
        304
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "f7a2c29e-5ccf-49ef-80f8-fed21cb3ca9b",
      "name": "Publish IG Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2272,
        304
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v19.0/YOUR_IG_ACCOUNT_ID/media_publish",
        "method": "POST",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "creation_id",
              "value": "={{ $json.id }}"
            },
            {
              "name": "access_token",
              "value": "YOUR_META_ACCESS_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "090b782f-798b-4c4b-9a9d-f9cecb77bdfa",
      "name": "Post to Facebook - Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2480,
        304
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v19.0/YOUR_FB_PAGE_ID/photos",
        "method": "POST",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $('Prepare Post Data').first().json.media_url }}"
            },
            {
              "name": "message",
              "value": "={{ $('Prepare Post Data').first().json.caption }}"
            },
            {
              "name": "access_token",
              "value": "YOUR_FB_PAGE_ACCESS_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "807d87b3-82e4-44ea-a1e3-586dd8b7e959",
      "name": "Create IG Reel Container",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1872,
        464
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v19.0/YOUR_IG_ACCOUNT_ID/media",
        "method": "POST",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "video_url",
              "value": "={{ $json.media_url }}"
            },
            {
              "name": "caption",
              "value": "={{ $json.caption }}"
            },
            {
              "name": "media_type",
              "value": "REELS"
            },
            {
              "name": "access_token",
              "value": "YOUR_META_ACCESS_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "05fe5674-aa62-45f4-b151-ea06686f2c99",
      "name": "Wait 60s - Reel Processing",
      "type": "n8n-nodes-base.wait",
      "position": [
        2080,
        464
      ],
      "parameters": {
        "amount": 60
      },
      "typeVersion": 1.1
    },
    {
      "id": "85fa63dd-8488-4256-a428-3b8a72cdde49",
      "name": "Check Reel Status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2272,
        464
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v19.0/{{ $json.id }}",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "fields",
              "value": "status_code"
            },
            {
              "name": "access_token",
              "value": "YOUR_META_ACCESS_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "2f7db70e-47c4-44e3-a7dc-b725ad69150e",
      "name": "Wait 15s - Safety Buffer",
      "type": "n8n-nodes-base.wait",
      "position": [
        2480,
        464
      ],
      "parameters": {
        "amount": 15
      },
      "typeVersion": 1.1
    },
    {
      "id": "326519f1-0a68-4a34-bd84-ad01d74bcf4f",
      "name": "Publish IG Reel",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2672,
        464
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v19.0/YOUR_IG_ACCOUNT_ID/media_publish",
        "method": "POST",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "creation_id",
              "value": "={{ $json.id }}"
            },
            {
              "name": "access_token",
              "value": "YOUR_META_ACCESS_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "9e184de0-6a30-48ae-ab92-5d852b65c9d9",
      "name": "Post to Facebook - Reel",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2880,
        464
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v19.0/YOUR_FB_PAGE_ID/videos",
        "method": "POST",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "file_url",
              "value": "={{ $('Prepare Post Data').first().json.media_url }}"
            },
            {
              "name": "description",
              "value": "={{ $('Prepare Post Data').first().json.caption }}"
            },
            {
              "name": "access_token",
              "value": "YOUR_FB_PAGE_ACCESS_TOKEN"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "d3c6971b-3801-4a99-90f0-35d5ba446704",
      "name": "Update Sheet - Success",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3280,
        368
      ],
      "parameters": {
        "columns": {
          "value": {
            "status": "posted",
            "post_id": "={{ $('Prepare Post Data').first().json.post_id }}",
            "image_url": "={{ $('Prepare Post Data').first().json.media_url }}",
            "posted_at": "={{ $now.toISO() }}",
            "instagram_id": "={{ $json.id || '' }}"
          },
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "post_id"
          ]
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "1301948859"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "=YOUR_GOOGLE_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "5ce4f2be-b1b6-49fe-a1c9-6df68edb9bb0",
      "name": "Update Sheet - Error",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3280,
        560
      ],
      "parameters": {
        "columns": {
          "value": {
            "status": "failed",
            "post_id": "={{ $('Prepare Post Data').first().json.post_id }}",
            "error_message": "={{ $json.error?.message || JSON.stringify($json) }}"
          },
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "post_id"
          ]
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "1301948859"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "=YOUR_GOOGLE_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "61d2346a-f879-4517-9989-fb3e9e5026e1",
      "name": "Merge Results",
      "type": "n8n-nodes-base.noOp",
      "position": [
        3120,
        304
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "dec7df4c-905f-4ffa-b084-137471ab7d57",
      "name": "Create a post",
      "type": "n8n-nodes-base.linkedIn",
      "position": [
        2896,
        304
      ],
      "parameters": {
        "text": "={{ $('Prepare Post Data').first().json.caption }}",
        "person": "YOUR_LINKEDIN_PERSON_ID",
        "additionalFields": {},
        "shareMediaCategory": "IMAGE"
      },
      "credentials": {
        "linkedInOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6de1e665-461d-477b-bfdc-1c5c1ca719bd",
      "name": "Download Image for LinkedIn",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2688,
        304
      ],
      "parameters": {
        "url": "={{ $('Prepare Post Data').first().json.media_url }}",
        "options": {
          "response": {
            "response": {}
          }
        }
      },
      "typeVersion": 4.4
    }
  ],
  "active": false,
  "settings": {
    "timezone": "Africa/Casablanca",
    "binaryMode": "separate",
    "callerPolicy": "workflowsFromSameOwner",
    "timeSavedMode": "fixed",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "dbe616d6-b436-4bf9-80ee-cee2b27b9a89",
  "connections": {
    "Create a post": {
      "main": [
        [
          {
            "node": "Merge Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Results": {
      "main": [
        [
          {
            "node": "Update Sheet - Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch Format": {
      "main": [
        [
          {
            "node": "Create IG Image Container",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create IG Reel Container",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish IG Reel": {
      "main": [
        [
          {
            "node": "Post to Facebook - Reel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish IG Image": {
      "main": [
        [
          {
            "node": "Post to Facebook - Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Read Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 15s - Image": {
      "main": [
        [
          {
            "node": "Publish IG Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Reel Status": {
      "main": [
        [
          {
            "node": "Wait 15s - Safety Buffer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Post Data": {
      "main": [
        [
          {
            "node": "Switch Format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Google Sheet": {
      "main": [
        [
          {
            "node": "Filter Today's Pending",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Today's Pending": {
      "main": [
        [
          {
            "node": "Prepare Post Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Facebook - Reel": {
      "main": [
        [
          {
            "node": "Merge Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create IG Reel Container": {
      "main": [
        [
          {
            "node": "Wait 60s - Reel Processing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Facebook - Image": {
      "main": [
        [
          {
            "node": "Download Image for LinkedIn",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 15s - Safety Buffer": {
      "main": [
        [
          {
            "node": "Publish IG Reel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create IG Image Container": {
      "main": [
        [
          {
            "node": "Wait 15s - Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 60s - Reel Processing": {
      "main": [
        [
          {
            "node": "Check Reel Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Image for LinkedIn": {
      "main": [
        [
          {
            "node": "Create a post",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}