{
  "nodes": [
    {
      "id": "7bd30fa4-5d9b-40d9-881f-1874d6b50aa5",
      "name": "Sort Instagram Results",
      "type": "n8n-nodes-base.code",
      "notes": "### What the system does:\nLaunches Instagram hashtag scraping via Apify's Instagram scraper\nSearches recent posts (last 7 days) under specified hashtags\nImplements 30-second processing wait for data collection completion\nRetrieves Instagram post data including likes, comments, and captions\nFilters and processes main posts (excluding carousel items and stories)\nApplies Instagram-specific engagement scoring for content ranking\n\n**Instagram Scoring Formula:**\n- Likes: 1 point each\n- Comments: 2 points each (emphasizing meaningful engagement)\n- Final score = (likes \u00d7 1) + (comments \u00d7 2)\n\n### Result:\n\u2705 Top 10 most engaging Instagram posts identified\n\u2705 Visual content performance metrics captured\n\u2705 Influencer and brand content engagement measured\n\u2705 Platform-specific engagement patterns analyzed",
      "position": [
        1504,
        2544
      ],
      "parameters": {
        "jsCode": "// Code pour n\u0153ud Code n8n - Classement Instagram avec output simplifi\u00e9\n// R\u00e9cup\u00e9rer les donn\u00e9es d'entr\u00e9e\nconst items = $input.all();\n\n// Filtrer uniquement les posts principaux (exclure les carousel_item)\nconst posts = items.filter(item => {\n  const post = item.json;\n  return post.productType !== 'carousel_item' && post.url && post.url.includes('/p/');\n});\n\n// Calculer le score pour chaque post\nconst postsWithScore = posts.map(item => {\n  const post = item.json;\n  \n  // likesCount peut \u00eatre -1 si masqu\u00e9 par Instagram \u2192 on traite comme 0\n  const likes = (post.likesCount && post.likesCount > 0) ? post.likesCount : 0;\n  const comments = post.commentsCount || 0;\n  \n  // Calcul du score : (likes \u00d7 1) + (comments \u00d7 2)\n  const totalScore = (likes * 1) + (comments * 2);\n  \n  return {\n    json: {\n      url: post.url,\n      caption: post.caption || \"Pas de caption\",\n      score: totalScore,\n      details: {\n        likes: likes,\n        comments: comments,\n        type: post.type,\n        author: post.ownerUsername || 'inconnu',\n        timestamp: post.timestamp\n      }\n    }\n  };\n});\n\n// Trier par score d\u00e9croissant\nconst sortedPosts = postsWithScore.sort((a, b) => b.json.score - a.json.score);\n\n// Prendre les 10 meilleurs\nconst top10Posts = sortedPosts.slice(0, 10);\n\n// Ajouter un rang \u00e0 chaque post\nconst rankedPosts = top10Posts.map((post, index) => ({\n  json: {\n    rank: index + 1,\n    url: post.json.url,\n    caption: post.json.caption,\n    score: post.json.score\n  }\n}));\n\n// Log pour debug\nconsole.log(`\ud83c\udfc6 TOP 10 POSTS INSTAGRAM - Score = (likes\u00d71) + (comments\u00d72)`);\nconsole.log(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);\nrankedPosts.forEach((post) => {\n  const p = post.json;\n  const shortCaption = p.caption.length > 60 ? p.caption.substring(0, 60) + '...' : p.caption;\n  console.log(`${p.rank}. Score: ${p.score}`);\n  console.log(`   URL: ${p.url}`);\n  console.log(`   Caption: \"${shortCaption}\"`);\n  console.log(`   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);\n});\nconsole.log(`\\n\ud83d\udcca Analys\u00e9 ${posts.length} posts au total`);\n\nreturn rankedPosts;"
      },
      "notesInFlow": true,
      "typeVersion": 2
    },
    {
      "id": "250a1c09-2596-402e-b2ba-7f4bd3a2e99b",
      "name": "Scheduled Run Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        624,
        2544
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "f9fd04d6-364f-4432-9322-94cfcce56c4f",
      "name": "Read Queries from Table",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        832,
        2544
      ],
      "parameters": {
        "operation": "get",
        "returnAll": true,
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "BYMzHVIbNU0mmvAZ",
          "cachedResultUrl": "/projects/oTpNUA7ZOCuhiQA0/datatables/BYMzHVIbNU0mmvAZ",
          "cachedResultName": "Query social media"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "bc8ad46c-3107-4091-b179-d6bca7b20fe4",
      "name": "Send Instagram Report Email",
      "type": "n8n-nodes-base.gmail",
      "notes": "Send dahsboard with top 10 of the most engaging post ",
      "position": [
        1984,
        2544
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Trends Social Media - {{ $('Loop Over Queries1').first().json.Query }}</title>\n    <style>\n        * {\n            margin: 0;\n            padding: 0;\n            box-sizing: border-box;\n        }\n\n        body {\n            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n            line-height: 1.6;\n            color: #333;\n            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n            min-height: 100vh;\n            padding: 20px;\n        }\n\n        .newsletter-container {\n            max-width: 1200px;\n            margin: 0 auto;\n            background: white;\n            border-radius: 20px;\n            overflow: hidden;\n            box-shadow: 0 20px 40px rgba(0,0,0,0.1);\n        }\n\n        .header {\n            background: linear-gradient(135deg, #ff6b6b, #ee5a24);\n            color: white;\n            padding: 40px 30px;\n            text-align: center;\n        }\n\n        .header h1 {\n            font-size: 2.8em;\n            margin-bottom: 10px;\n            font-weight: 700;\n        }\n\n        .header p {\n            font-size: 1.2em;\n            opacity: 0.9;\n            margin-bottom: 15px;\n        }\n\n        .keyword-badge {\n            display: inline-block;\n            background: rgba(255,255,255,0.2);\n            color: white;\n            padding: 8px 20px;\n            border-radius: 20px;\n            font-size: 1em;\n            font-weight: 600;\n            backdrop-filter: blur(10px);\n        }\n\n        .stats-overview {\n            display: grid;\n            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n            gap: 20px;\n            padding: 30px;\n            background: #f8f9fa;\n        }\n\n        .stat-card {\n            background: white;\n            padding: 20px;\n            border-radius: 15px;\n            text-align: center;\n            box-shadow: 0 5px 15px rgba(0,0,0,0.08);\n            border-left: 4px solid;\n        }\n\n        .stat-card.high { border-left-color: #ff4757; }\n        .stat-card.medium { border-left-color: #ffa502; }\n        .stat-card.low { border-left-color: #70a1ff; }\n\n        .stat-number {\n            font-size: 2.5em;\n            font-weight: bold;\n            margin-bottom: 5px;\n        }\n\n        .stat-label {\n            color: #666;\n            font-size: 0.9em;\n            text-transform: uppercase;\n            letter-spacing: 1px;\n        }\n\n        .table-container {\n            margin: 30px;\n            background: white;\n            border-radius: 15px;\n            overflow: hidden;\n            box-shadow: 0 10px 25px rgba(0,0,0,0.1);\n        }\n\n        .table-header {\n            background: linear-gradient(135deg, #2c3e50, #34495e);\n            color: white;\n            padding: 25px 30px;\n            text-align: center;\n        }\n\n        .table-title {\n            font-size: 1.8em;\n            font-weight: 600;\n            margin-bottom: 5px;\n        }\n\n        .table-subtitle {\n            opacity: 0.8;\n            font-size: 1em;\n        }\n\n        .trends-table {\n            width: 100%;\n            border-collapse: collapse;\n            font-size: 0.95em;\n        }\n\n        .trends-table th {\n            background: #f8f9fa;\n            padding: 15px 12px;\n            text-align: left;\n            font-weight: 600;\n            color: #555;\n            border-bottom: 2px solid #dee2e6;\n            text-transform: uppercase;\n            font-size: 0.8em;\n            letter-spacing: 0.5px;\n        }\n\n        .trends-table td {\n            padding: 15px 12px;\n            border-bottom: 1px solid #eee;\n            vertical-align: middle;\n            text-align: center;\n        }\n\n        .trends-table td:nth-child(3),\n        .trends-table td:nth-child(4) {\n            text-align: left;\n        }\n\n        .trends-table tr:nth-child(even) {\n            background-color: #f8f9fa;\n        }\n\n        .trends-table tr:hover {\n            background-color: #e3f2fd;\n            transform: scale(1.01);\n            transition: all 0.2s ease;\n        }\n\n        .rank-number {\n            font-weight: bold;\n            font-size: 1.2em;\n            color: #2c3e50;\n        }\n\n        .rank-number.top3 {\n            color: #ff6b6b;\n            font-size: 1.4em;\n        }\n\n        .source-badge {\n            padding: 6px 12px;\n            border-radius: 20px;\n            font-size: 0.8em;\n            font-weight: 600;\n            text-transform: uppercase;\n            letter-spacing: 0.5px;\n        }\n\n        .source-badge.tiktok {\n            background: #ff0050;\n            color: white;\n        }\n\n        .source-badge.reddit {\n            background: #ff4500;\n            color: white;\n        }\n\n        .source-badge.instagram {\n            background: #e4405f;\n            color: white;\n        }\n\n        .level-badge {\n            padding: 4px 10px;\n            border-radius: 15px;\n            font-size: 0.75em;\n            font-weight: 600;\n            text-transform: uppercase;\n        }\n\n        .level-badge.high {\n            background: #ff4757;\n            color: white;\n        }\n\n        .level-badge.medium {\n            background: #ffa502;\n            color: white;\n        }\n\n        .level-badge.low {\n            background: #70a1ff;\n            color: white;\n        }\n\n        .content-text {\n            max-width: 250px;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            white-space: nowrap;\n            color: #555;\n            line-height: 1.4;\n        }\n\n        .author-link {\n            color: #667eea;\n            text-decoration: none;\n            font-weight: 600;\n        }\n\n        .author-link:hover {\n            text-decoration: underline;\n        }\n\n        .score-number {\n            font-weight: bold;\n            color: #2c3e50;\n            font-size: 1.1em;\n        }\n\n        .footer {\n            text-align: center;\n            padding: 30px;\n            background: #f8f9fa;\n            color: #666;\n            border-top: 1px solid #eee;\n        }\n\n        .footer p {\n            margin-bottom: 10px;\n        }\n\n        .date-info {\n            font-size: 0.9em;\n            color: #888;\n        }\n\n        @media (max-width: 768px) {\n            .newsletter-container {\n                margin: 10px;\n                border-radius: 15px;\n            }\n            \n            .header {\n                padding: 30px 20px;\n            }\n            \n            .header h1 {\n                font-size: 2.2em;\n            }\n            \n            .table-container {\n                margin: 20px;\n                overflow-x: auto;\n            }\n            \n            .trends-table {\n                min-width: 800px;\n            }\n            \n            .stats-overview {\n                padding: 20px;\n                grid-template-columns: 1fr;\n            }\n        }\n    </style>\n</head>\n<body>\n    <div class=\"newsletter-container\">\n        <!-- Header -->\n        <header class=\"header\">\n            <h1>\ud83d\udcca R\u00e9capitulatif par Hashtag</h1>\n            <p>Scores totaux par r\u00e9seau social</p>\n        </header>\n\n        <!-- Hashtag Summary Table -->\n        <section class=\"table-container\" style=\"margin: 30px 30px 0 30px;\">\n            <table class=\"trends-table\">\n                <thead>\n                    <tr>\n                        <th>Hashtag</th>\n                        <th>TikTok</th>\n                        <th>Reddit</th>\n                        <th>Instagram</th>\n                        <th>Score Total</th>\n                    </tr>\n                </thead>\n                <tbody>\n                    <tr>\n                        <td>\n                            <span style=\"font-weight: bold; color: #ff6b6b; font-size: 1.1em;\">#{{ $('Loop Over Queries1').first().json.Query }}</span>\n                        </td>\n                        <td>\n                            <span class=\"score-number\">{{ $('Rank Instagram Posts1').all().filter(item => item.json.source === 'TikTok').reduce((sum, item) => sum + item.json.score, 0).toLocaleString('fr-FR') }}</span>\n                        </td>\n                        <td>\n                            <span class=\"score-number\">{{ $('Rank Instagram Posts1').all().filter(item => item.json.source === 'Reddit').reduce((sum, item) => sum + item.json.score, 0).toLocaleString('fr-FR') }}</span>\n                        </td>\n                        <td>\n                            <span class=\"score-number\">{{ $('Rank Instagram Posts1').all().filter(item => item.json.source === 'Instagram').reduce((sum, item) => sum + item.json.score, 0).toLocaleString('fr-FR') }}</span>\n                        </td>\n                        <td>\n                            <span class=\"score-number\" style=\"color: #ff6b6b; font-size: 1.2em;\">{{ $('Rank Instagram Posts1').all().reduce((sum, item) => sum + item.json.score, 0).toLocaleString('fr-FR') }}</span>\n                        </td>\n                    </tr>\n                </tbody>\n            </table>\n        </section>\n\n        <!-- Main Table -->\n        <section class=\"table-container\">\n            <div class=\"table-header\">\n                <div class=\"table-title\">#{{ $('Loop Over Queries1').first().json.Query }}</div>\n                <div class=\"table-subtitle\"></div>\n            </div>\n            \n            <table class=\"trends-table\">\n                <thead>\n                    <tr>\n                        <th>Rang</th>\n                        <th>Source</th>\n                        <th>Auteur</th>\n                        <th>Contenu</th>\n                        <th>Score</th>\n                        <th>Level</th>\n                    </tr>\n                </thead>\n                <tbody>\n                    {{ $('Rank Instagram Posts1').all().map(item => `\n                        <tr onclick=\"window.open('${item.json.url}', '_blank')\" style=\"cursor: pointer;\">\n                            <td>\n                                <span class=\"rank-number ${item.json.rank <= 3 ? 'top3' : ''}\">${item.json.rank}</span>\n                            </td>\n                            <td>\n                                <span class=\"source-badge ${item.json.source.toLowerCase()}\">${item.json.source}</span>\n                            </td>\n                            <td>\n                                <a href=\"${item.json.url}\" target=\"_blank\" class=\"author-link\">${item.json.author}</a>\n                            </td>\n                            <td>\n                                <div class=\"content-text\" title=\"${item.json.content}\">${item.json.content}</div>\n                            </td>\n                            <td>\n                                <span class=\"score-number\">${item.json.score.toLocaleString('fr-FR')}</span>\n                            </td>\n                            <td>\n                                <span class=\"level-badge ${item.json.level.toLowerCase()}\">${item.json.level}</span>\n                            </td>\n                        </tr>\n                    `).join('') }}\n                </tbody>\n            </table>\n        </section>\n\n        <!-- Footer -->\n        <footer class=\"footer\">\n            <p><strong>Social Media Trends Dashboard</strong></p>\n            <p>Analyse automatis\u00e9e des contenus par mot-cl\u00e9</p>\n            <div class=\"date-info\">\n                <p>G\u00e9n\u00e9r\u00e9 le {{ new Date().toLocaleDateString('fr-FR', { \n                    year: 'numeric', \n                    month: 'long', \n                    day: 'numeric', \n                    hour: '2-digit', \n                    minute: '2-digit' \n                }) }}</p>\n            </div>\n        </footer>\n    </div>\n</body>\n</html>",
        "options": {},
        "subject": "Social media monitoring"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "executeOnce": true,
      "notesInFlow": true,
      "typeVersion": 2.1
    },
    {
      "id": "7b695b73-05bd-4468-b089-2fa91a8211ed",
      "name": "Save Results to Data Table",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1984,
        2416
      ],
      "parameters": {
        "columns": {
          "value": {
            "url": "={{ $json.url }}",
            "Date": "={{ $now.toISO() }}",
            "rank": "={{ $json.rank }}",
            "level": "={{ $json.level }}",
            "score": "={{ $json.score }}",
            "author": "={{ $json.author }}",
            "source": "={{ $json.source }}",
            "content": "={{ $json.content }}",
            "keyword": "={{ $json.keyword }}"
          },
          "schema": [
            {
              "id": "rank",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "rank",
              "defaultMatch": false
            },
            {
              "id": "keyword",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "keyword",
              "defaultMatch": false
            },
            {
              "id": "source",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "source",
              "defaultMatch": false
            },
            {
              "id": "author",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "author",
              "defaultMatch": false
            },
            {
              "id": "content",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "content",
              "defaultMatch": false
            },
            {
              "id": "score",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "score",
              "defaultMatch": false
            },
            {
              "id": "level",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "level",
              "defaultMatch": false
            },
            {
              "id": "url",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "url",
              "defaultMatch": false
            },
            {
              "id": "Date",
              "type": "dateTime",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "75Jvx9ALCoEGcdwY",
          "cachedResultUrl": "/projects/oTpNUA7ZOCuhiQA0/datatables/75Jvx9ALCoEGcdwY",
          "cachedResultName": "Trend Social media"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "61231991-602c-4ef5-aeed-b8e5606de43e",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        2240
      ],
      "parameters": {
        "width": 480,
        "height": 896,
        "content": "## Untitled workflow\n\n### How it works\n\n1. A scheduled trigger fires periodically and fetches a list of search queries from a data table.\n2. The workflow loops over each query one at a time using a batch iterator.\n3. For each query, Instagram posts are fetched via the Apify API.\n4. The raw post data is sorted and then ranked using custom code.\n5. The ranked results are stored back into a data table and sent as a Gmail notification.\n6. The loop continues with the next query until all queries are processed.\n\n### Setup steps\n\n- - [ ] Configure the **Reddit Schedule Trigger** with the desired run frequency (e.g., daily, hourly).\n- - [ ] Set up the **Reddit Get row(s)** data table with the list of Instagram search queries to process.\n- - [ ] Add your **Apify API key** to the `Insta get posts solo` HTTP Request node (URL/auth configuration).\n- - [ ] Connect your **Gmail account** credentials to the `Reddit Send a message1` node and set the recipient email address.\n- - [ ] Configure the **Reddot Push to data table** node to point to the correct destination data table for storing results.\n\n### Customization\n\nYou can adjust the ranking and sorting logic inside the `Sort Instagram solo` and `Classement Instagram` code nodes to change how posts are scored or filtered. The batch size in `Reddit Loop Over Query` can also be tuned depending on API rate limits."
      },
      "typeVersion": 1
    },
    {
      "id": "8e08c7c3-ecd9-4937-9d7b-72c48fac1e51",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        576,
        2384
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 320,
        "content": "## Schedule trigger and query fetch\n\nA scheduled trigger fires the workflow and retrieves the list of Instagram search queries stored in a data table."
      },
      "typeVersion": 1
    },
    {
      "id": "baf1d1b8-dad5-4fcf-87d0-9f80ebbd05d5",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1056,
        2416
      ],
      "parameters": {
        "color": 7,
        "width": 592,
        "height": 304,
        "content": "## Loop and fetch Instagram posts\n\nIterates over each query in batches, calls the Apify Instagram API for each one, and collects the raw post data."
      },
      "typeVersion": 1
    },
    {
      "id": "936ff1d1-7a62-48c9-9d82-5b1711bc0a16",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1696,
        2240
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 464,
        "content": "## Rank results and send output\n\nRanks the sorted Instagram posts using custom code, then simultaneously saves the results to a data table and sends a Gmail notification before looping back to the next query."
      },
      "typeVersion": 1
    },
    {
      "id": "ac1436af-4006-400b-bad9-f15807682fdd",
      "name": "Loop Over Queries1",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1104,
        2544
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "d13ce838-7324-4549-bb7f-8a6eef0631c8",
      "name": "Rank Instagram Posts1",
      "type": "n8n-nodes-base.code",
      "notes": "Sorts all posts + give them points depending on their likes + comments",
      "position": [
        1744,
        2544
      ],
      "parameters": {
        "jsCode": "// Code pour n\u0153ud Code n8n - Classement Instagram\n// R\u00e9cup\u00e9rer le keyword dynamiquement\nconst keyword = $('Loop Over Query').first().json.Query;\n\n// R\u00e9cup\u00e9rer les donn\u00e9es du n\u0153ud pr\u00e9c\u00e9dent\nconst instagramData = $('Sort Instagram').all();\n\nconsole.log(`\ud83d\udce5 R\u00e9cup\u00e9ration des donn\u00e9es:`);\nconsole.log(`- Instagram: ${instagramData.length} posts`);\n\n// Fonction pour d\u00e9terminer le level bas\u00e9 sur le score\nfunction getLevel(score) {\n  if (score >= 10000) return 'High';\n  if (score >= 1000) return 'Medium';\n  return 'Low';\n}\n\n// Fonction pour extraire l'auteur Instagram\nfunction getAuthor(item) {\n  const instaMatch = item.url.match(/instagram\\.com\\/([^\\/]+)/);\n  return instaMatch ? `@${instaMatch[1]}` : '@inconnu';\n}\n\n// Transformer les donn\u00e9es Instagram\nconst instagramPosts = instagramData.map(item => ({\n  json: {\n    source: 'Instagram',\n    keyword: keyword,\n    author: getAuthor(item.json),\n    content: (item.json.caption || 'Pas de caption').substring(0, 50) + '...',\n    score: item.json.score,\n    level: getLevel(item.json.score),\n    url: item.json.url,\n    originalRank: item.json.rank\n  }\n}));\n\n// Trier par score d\u00e9croissant\nconst sortedPosts = instagramPosts.sort((a, b) => b.json.score - a.json.score);\n\n// Ajouter le rang\nconst rankedPosts = sortedPosts.map((post, index) => ({\n  json: {\n    ...post.json,\n    rank: index + 1,\n    date: new Date().toISOString().split('T')[0]\n  }\n}));\n\n// Prendre le top 15\nconst topPosts = rankedPosts.slice(0, 15);\n\n// Statistiques par niveau\nconst stats = {\n  total: topPosts.length,\n  byLevel: {\n    High: topPosts.filter(p => p.json.level === 'High').length,\n    Medium: topPosts.filter(p => p.json.level === 'Medium').length,\n    Low: topPosts.filter(p => p.json.level === 'Low').length\n  }\n};\n\n// Log pour debug\nconsole.log(`\ud83c\udfc6 TOP ${topPosts.length} POSTS INSTAGRAM - Mot-cl\u00e9: \"${keyword}\"`);\nconsole.log(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);\n\ntopPosts.forEach((post) => {\n  const p = post.json;\n  console.log(`${p.rank}. ${p.author} - Score: ${p.score.toLocaleString()} (${p.level})`);\n  console.log(`   Contenu: \"${p.content}\"`);\n  console.log(`   URL: ${p.url}`);\n  console.log(`   \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);\n});\n\nconsole.log(`\\n\ud83d\udcca STATISTIQUES:`);\nconsole.log(`Total: ${stats.total} posts`);\nconsole.log(`Par niveau: High(${stats.byLevel.High}) | Medium(${stats.byLevel.Medium}) | Low(${stats.byLevel.Low})`);\n\n// Retourner le classement\nreturn topPosts;"
      },
      "notesInFlow": true,
      "typeVersion": 2
    },
    {
      "id": "9a9d636a-458c-45b0-9d94-53b9265429b6",
      "name": "Fetch Instagram Posts via Apify1",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Post the request on apify",
      "position": [
        1312,
        2544
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/reGe1ST3OBgYZSsZJ/run-sync-get-dataset-items",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n    \"hashtags\": [\n        \"{{ $json.Query.replace(/\\s+/g, '') }}\"\n    ],\n    \"keywordSearch\": false,\n    \"resultsLimit\": 50,\n    \"resultsType\": \"posts\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "apifyApi"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        },
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "executeOnce": false,
      "notesInFlow": true,
      "retryOnFail": true,
      "typeVersion": 4.2
    }
  ],
  "connections": {
    "Loop Over Queries1": {
      "main": [
        [],
        [
          {
            "node": "Fetch Instagram Posts via Apify1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rank Instagram Posts1": {
      "main": [
        [
          {
            "node": "Send Instagram Report Email",
            "type": "main",
            "index": 0
          },
          {
            "node": "Save Results to Data Table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scheduled Run Trigger": {
      "main": [
        [
          {
            "node": "Read Queries from Table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sort Instagram Results": {
      "main": [
        [
          {
            "node": "Rank Instagram Posts1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Queries from Table": {
      "main": [
        [
          {
            "node": "Loop Over Queries1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Instagram Report Email": {
      "main": [
        [
          {
            "node": "Loop Over Queries1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Instagram Posts via Apify1": {
      "main": [
        [
          {
            "node": "Sort Instagram Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}