Système automatisé de gestion de campagnes d'influence marketing
Ceci est unContent Creation, Multimodal AIworkflow d'automatisation du domainecontenant 24 nœuds.Utilise principalement des nœuds comme If, Code, Gmail, Merge, Switch. Automatiser l'évaluation d'influenceurs et la gestion de campagnes avec les API Instagram/YouTube
- •Compte Google et informations d'identification Gmail API
- •Point de terminaison HTTP Webhook (généré automatiquement par n8n)
- •Peut nécessiter les informations d'identification d'authentification de l'API cible
- •Informations d'identification Google Sheets API
Nœuds utilisés (24)
Catégorie
{
"id": "FTBefJJksAo6vP1K",
"meta": {
"instanceId": "e56288a9b12ad2dc7c19cc4170f20f7abcacaad5fb3972dd882c9ce4f34e7668",
"templateCredsSetupCompleted": true
},
"name": "Automated Influencer Campaign Management System",
"tags": [],
"nodes": [
{
"id": "12f8177d-3695-45f1-badb-4fd24c4e149c",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
0,
0
],
"webhookId": "8af0a960-bcc4-4b06-bfb6-698007cad216",
"parameters": {
"path": "/YOUR_CUSTOM_WEBHOOK_PATH",
"options": {
"rawBody": false
},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "bb59a3b4-d17d-4eb0-b2de-26df8ea7fd6f",
"name": "Nettoyeur de données",
"type": "n8n-nodes-base.code",
"position": [
224,
0
],
"parameters": {
"jsCode": "// Debug: Log the incoming data first\nconsole.log('Incoming data:', JSON.stringify($input.all(), null, 2));\n\n// Get the data from webhook\nconst inputData = $input.first();\nconsole.log('Input item:', JSON.stringify(inputData, null, 2));\n\n// Extract JSON data (webhook data is nested differently)\nlet data;\nif (inputData.json.body) {\n // If data comes in request body\n data = inputData.json.body;\n} else if (inputData.json.query) {\n // If data comes as query parameters\n data = inputData.json.query;\n} else {\n // Direct JSON data\n data = inputData.json;\n}\n\nconsole.log('Processed data:', JSON.stringify(data, null, 2));\n\n// Handle case where data might be a string (needs parsing)\nif (typeof data === 'string') {\n try {\n data = JSON.parse(data);\n } catch (e) {\n throw new Error('Invalid JSON format in request');\n }\n}\n\n// Required fields validation\nconst required = ['name', 'email', 'social_handles', 'niche', 'country'];\nconst missing = required.filter(field => !data || !data[field]);\n\nif (missing.length > 0) {\n console.log('Available fields:', Object.keys(data || {}));\n throw new Error(`Missing required fields: ${missing.join(', ')}. Available fields: ${Object.keys(data || {}).join(', ')}`);\n}\n\n// Email format validation\nconst emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nif (!emailRegex.test(data.email)) {\n throw new Error('Invalid email format');\n}\n\n// Clean social handles (remove @ symbols, extract usernames)\nconst cleanHandles = {};\nfor (const [platform, handle] of Object.entries(data.social_handles)) {\n if (handle) {\n cleanHandles[platform] = handle.replace(/[@\\/]/g, '').split('/').pop();\n }\n}\n\nreturn [{\n json: {\n ...data,\n social_handles: cleanHandles,\n created_at: new Date().toISOString(),\n status: 'pending_validation'\n }\n}];"
},
"typeVersion": 2
},
{
"id": "62f128f9-6a68-4d78-baae-908153106221",
"name": "Vérification d'email",
"type": "n8n-nodes-verifiemail.verifiEmail",
"position": [
448,
0
],
"parameters": {
"email": "={{ $json.email }}"
},
"credentials": {
"verifiEmailApi": {
"id": "Hnczc7sz8SvYDR0g",
"name": "VerifiEmail account 2"
}
},
"typeVersion": 1
},
{
"id": "afbbc1e1-76c2-4ca1-a75f-a7fe0946f130",
"name": "Commutateur",
"type": "n8n-nodes-base.switch",
"position": [
624,
0
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "aea5e85b-3bb5-4db3-942b-7ada2f17ab2a",
"operator": {
"type": "boolean",
"operation": "equals"
},
"leftValue": "={{ $json.valid }}",
"rightValue": true
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "de79caea-c28e-47da-bc90-c2d6ca9a94e3",
"operator": {
"type": "boolean",
"operation": "equals"
},
"leftValue": "={{ $json.valid }}",
"rightValue": false
}
]
}
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "a01052ae-f470-44c9-bbd0-b9dc44e241c0",
"name": "Arrêt et erreur",
"type": "n8n-nodes-base.stopAndError",
"position": [
496,
288
],
"parameters": {
"errorMessage": "invalid email"
},
"typeVersion": 1
},
{
"id": "9a885214-eb51-4f09-92b6-92f202a28245",
"name": "Statistiques du profil Instagram",
"type": "n8n-nodes-base.httpRequest",
"position": [
928,
-256
],
"parameters": {
"url": "https://instagram120.p.rapidapi.com/api/instagram/profile",
"method": "POST",
"options": {},
"sendBody": true,
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "username",
"value": "={{ $('Data Sanitizer').item.json.social_handles.instagram }}"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "x-rapidapi-host",
"value": "instagram120.p.rapidapi.com"
},
{
"name": "x-rapidapi-key",
"value": "YOUR_RAPIDAPI_KEY_HERE"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "d77393c1-9fc2-45bc-9b13-b48f5c3593bf",
"name": "Analyse des données Instagram",
"type": "n8n-nodes-base.code",
"position": [
1328,
-112
],
"parameters": {
"jsCode": "const instagramResponse = $input.first().json;\n\n// Get the user data from a previous node (you need to reference the correct node name)\nlet userData;\ntry {\n // Replace 'Data Sanitizer' with your actual previous node name that has user data\n userData = $('Data Sanitizer').first().json;\n} catch (e) {\n // Fallback if node reference fails\n userData = {\n name: 'Test User',\n email: 'test@example.com',\n niche: 'sports',\n country: 'US',\n rate_card: 1000,\n social_handles: { instagram: 'cristiano' }\n };\n}\n\nconsole.log('User Data:', JSON.stringify(userData, null, 2));\nconsole.log('Instagram Response:', JSON.stringify(instagramResponse, null, 2));\n\ntry {\n const profileData = instagramResponse.result;\n \n if (!profileData) {\n throw new Error('No Instagram profile data found');\n }\n\n // Parse the real Instagram data from RapidAPI\n const instagramData = {\n id: profileData.id,\n username: profileData.username,\n followers: profileData.edge_followed_by.count || 0,\n following: profileData.edge_follow.count || 0,\n posts_count: profileData.edge_owner_to_timeline_media.count || 0,\n is_private: profileData.is_private || false,\n verified: profileData.is_verified || false,\n biography: profileData.biography || '',\n full_name: profileData.full_name || '',\n profile_pic_url: profileData.profile_pic_url || '',\n profile_pic_url_hd: profileData.profile_pic_url_hd || ''\n };\n \n // Calculate realistic engagement for mega-influencer (Cristiano)\n let engagement_rate = 1.2; // Mega influencers typically have lower engagement rates\n if (instagramData.followers < 1000000) {\n engagement_rate = 3.5; // Regular influencers\n } else if (instagramData.followers < 100000000) {\n engagement_rate = 1.8; // Major influencers \n }\n \n const avg_engagement = Math.floor(instagramData.followers * (engagement_rate / 100));\n \n instagramData.engagement_rate = parseFloat(engagement_rate.toFixed(2));\n instagramData.avg_engagement = avg_engagement;\n instagramData.avg_likes = Math.floor(avg_engagement * 0.85);\n instagramData.avg_comments = Math.floor(avg_engagement * 0.15);\n\n return [{\n json: {\n ...userData,\n social_stats: {\n instagram: {\n ...instagramData,\n api_source: 'rapidapi_real',\n fetched_at: new Date().toISOString()\n }\n }\n }\n }];\n \n} catch (error) {\n console.log('Parse error:', error.message);\n \n return [{\n json: {\n ...userData,\n social_stats: {\n instagram: {\n followers: 0,\n following: 0,\n posts_count: 0,\n verified: false,\n biography: '',\n username: userData.social_handles?.instagram || 'unknown',\n avg_engagement: 0,\n engagement_rate: 0,\n api_source: 'parse_failed',\n error: error.message,\n fetched_at: new Date().toISOString()\n }\n }\n }\n }];\n}"
},
"typeVersion": 2
},
{
"id": "4a2298b1-e9a9-4667-8482-fd2580810c24",
"name": "Statistiques de la chaîne YouTube",
"type": "n8n-nodes-base.httpRequest",
"position": [
928,
176
],
"parameters": {
"url": "https://youtube138.p.rapidapi.com/channel/details",
"options": {},
"sendQuery": true,
"sendHeaders": true,
"queryParameters": {
"parameters": [
{
"name": "id",
"value": "={{ $('Webhook').item.json.body.social_handles.youtube }}"
},
{
"name": "hl",
"value": "en"
},
{
"name": "gl",
"value": "US"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "x-rapidapi-host",
"value": "youtube138.p.rapidapi.com"
},
{
"name": "x-rapidapi-key",
"value": "YOUR_RAPIDAPI_KEY_HERE"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "0f58c1a3-b441-4e80-bc9a-010e4da46d2d",
"name": "Analyse des données YouTube",
"type": "n8n-nodes-base.code",
"position": [
1328,
80
],
"parameters": {
"jsCode": "const input = $input.first().json;\n\nconsole.log('Full YouTube input:', JSON.stringify(input, null, 2));\n\n// Try to get user data from previous nodes in the workflow\nlet userData;\ntry {\n // Try different possible node names - update these to match your actual node names\n userData = $('Parse Instagram Data').first().json || \n $('Data Sanitizer').first().json ||\n $('Process Email Validation').first().json ||\n $('Mock Instagram Data').first().json;\n \n console.log('Found user data from previous node:', JSON.stringify(userData, null, 2));\n} catch (e) {\n console.log('Could not find user data from previous nodes, using fallback');\n // Fallback user data for testing\n userData = {\n name: \"Sarah Johnson\",\n email: \"sarah.fitness@gmail.com\",\n niche: \"fitness\", \n country: \"US\",\n rate_card: 750,\n social_handles: {\n instagram: \"sarahfitlife\",\n youtube: \"SarahFitnessJourney\"\n },\n social_stats: {},\n created_at: new Date().toISOString(),\n status: 'processing'\n };\n}\n\n// Parse the YouTube channel data from the current input\nconst channelData = input;\n\ntry {\n if (!channelData.stats) {\n throw new Error('No YouTube stats found in response');\n }\n\n const youtubeData = {\n channel_id: channelData.channelId || '',\n username: channelData.username || '',\n title: channelData.title || '',\n subscribers: channelData.stats.subscribers || 0,\n subscribers_text: channelData.stats.subscribersText || '',\n total_views: channelData.stats.views || 0,\n video_count: channelData.stats.videos || 0,\n description: channelData.description || '',\n is_verified: channelData.isVerified || false,\n is_verified_artist: channelData.isVerifiedArtist || false,\n joined_date: channelData.joinedDate || '',\n joined_date_text: channelData.joinedDateText || '',\n country: channelData.country || '',\n has_business_email: channelData.hasBusinessEmail || false,\n avatar_url: channelData.avatar?.[0]?.url || '',\n banner_url: channelData.banner?.desktop?.[0]?.url || '',\n is_family_safe: channelData.isFamilySafe || true\n };\n\n // Calculate engagement metrics\n const avg_views_per_video = youtubeData.video_count > 0 ? \n Math.floor(youtubeData.total_views / youtubeData.video_count) : 0;\n \n // YouTube engagement rate: (avg views per video / subscribers) * 100\n const engagement_rate = youtubeData.subscribers > 0 ? \n parseFloat(((avg_views_per_video / youtubeData.subscribers) * 100).toFixed(2)) : 0;\n \n // Estimate social engagement based on YouTube norms\n const estimated_avg_likes = Math.floor(avg_views_per_video * 0.03); // ~3% of views\n const estimated_avg_comments = Math.floor(avg_views_per_video * 0.005); // ~0.5% of views\n const estimated_total_engagement = estimated_avg_likes + estimated_avg_comments;\n \n // Add calculated metrics\n youtubeData.avg_views_per_video = avg_views_per_video;\n youtubeData.engagement_rate = engagement_rate;\n youtubeData.estimated_avg_likes = estimated_avg_likes;\n youtubeData.estimated_avg_comments = estimated_avg_comments;\n youtubeData.estimated_total_engagement = estimated_total_engagement;\n\n // Channel age calculation (for scoring purposes)\n const joinedDate = new Date(channelData.joinedDate);\n const now = new Date();\n const monthsActive = Math.floor((now - joinedDate) / (1000 * 60 * 60 * 24 * 30));\n youtubeData.months_active = monthsActive;\n youtubeData.videos_per_month = monthsActive > 0 ? (youtubeData.video_count / monthsActive).toFixed(1) : 0;\n\n console.log('Successfully parsed YouTube data:', JSON.stringify(youtubeData, null, 2));\n\n return [{\n json: {\n ...userData,\n social_stats: {\n ...userData.social_stats,\n youtube: {\n ...youtubeData,\n api_source: 'rapidapi_real',\n fetched_at: new Date().toISOString()\n }\n }\n }\n }];\n \n} catch (error) {\n console.log('YouTube Parse Error:', error.message);\n \n return [{\n json: {\n ...userData,\n social_stats: {\n ...userData.social_stats,\n youtube: {\n channel_id: '',\n username: '',\n title: '',\n subscribers: 0,\n total_views: 0,\n video_count: 0,\n engagement_rate: 0,\n avg_views_per_video: 0,\n estimated_avg_likes: 0,\n estimated_avg_comments: 0,\n api_source: 'parse_failed',\n error: error.message,\n fetched_at: new Date().toISOString()\n }\n }\n }\n }];\n}"
},
"typeVersion": 2
},
{
"id": "bebd9b90-7868-4c26-9eec-18fa9a4754c5",
"name": "Fusion",
"type": "n8n-nodes-base.merge",
"position": [
1536,
-16
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "867b3df2-09b1-459c-a619-12e30c753782",
"name": "Calcul du score d'influence",
"type": "n8n-nodes-base.code",
"position": [
1760,
-16
],
"parameters": {
"jsCode": "const allData = $input.all(); // Get all items from merge node\nconsole.log('Number of merge items:', allData.length);\n\n// Find the item with both Instagram and YouTube data\nlet data;\nif (allData.length === 2) {\n // Two separate items from merge - combine them\n const item1 = allData[0].json;\n const item2 = allData[1].json;\n \n data = {\n ...item1,\n social_stats: {\n ...item1.social_stats,\n ...item2.social_stats\n }\n };\n} else {\n // Single item with both platforms\n data = allData[0].json;\n}\n\nconst socialStats = data.social_stats || {};\n\nconsole.log('Combined data check:', {\n hasInstagram: !!socialStats.instagram,\n hasYoutube: !!socialStats.youtube,\n instagramFollowers: socialStats.instagram?.followers,\n youtubeSubscribers: socialStats.youtube?.subscribers\n});\n\n// Rest of scoring configuration (same as before)\nconst SCORING_CONFIG = {\n platform_weights: {\n instagram: 0.6,\n youtube: 0.4\n },\n follower_tiers: {\n nano: { min: 1000, max: 10000, score: 50 },\n micro: { min: 10000, max: 100000, score: 70 },\n macro: { min: 100000, max: 1000000, score: 90 },\n mega: { min: 1000000, max: Infinity, score: 100 }\n },\n engagement_tiers: {\n youtube: {\n excellent: { min: 10, score: 100 },\n good: { min: 5, score: 85 },\n average: { min: 2, score: 65 },\n poor: { min: 0, score: 40 }\n },\n instagram: {\n excellent: { min: 6, score: 100 },\n good: { min: 3, score: 85 },\n average: { min: 1.5, score: 65 },\n poor: { min: 0, score: 40 }\n }\n }\n};\n\nfunction calculatePlatformScore(platformData, platform) {\n if (!platformData || platformData.error) return null;\n \n const followers = platformData.followers || platformData.subscribers || 0;\n const engagementRate = platformData.engagement_rate || 0;\n \n let followerScore = 40;\n for (const [tier, config] of Object.entries(SCORING_CONFIG.follower_tiers)) {\n if (followers >= config.min && followers <= config.max) {\n followerScore = config.score;\n break;\n }\n }\n \n let engagementScore = 40;\n const thresholds = SCORING_CONFIG.engagement_tiers[platform] || SCORING_CONFIG.engagement_tiers.instagram;\n \n for (const [tier, config] of Object.entries(thresholds)) {\n if (engagementRate >= config.min) {\n engagementScore = config.score;\n break;\n }\n }\n \n let qualityBonus = 0;\n if (platformData.verified || platformData.is_verified) qualityBonus += 10;\n if (platformData.has_business_email) qualityBonus += 5;\n if (platform === 'youtube' && parseFloat(platformData.videos_per_month) > 4) qualityBonus += 5;\n if (platform === 'instagram' && !platformData.is_private) qualityBonus += 5;\n \n const totalScore = Math.min(100, Math.round(\n (followerScore * 0.4) + \n (engagementScore * 0.5) + \n qualityBonus\n ));\n \n return {\n total: totalScore,\n breakdown: {\n follower_score: followerScore,\n engagement_score: engagementScore,\n quality_bonus: qualityBonus,\n followers: followers,\n engagement_rate: engagementRate,\n tier: followers >= 1000000 ? 'mega' : followers >= 100000 ? 'macro' : followers >= 10000 ? 'micro' : 'nano'\n }\n };\n}\n\n// Calculate scores for each platform\nconst scores = {};\nlet weightedScore = 0;\nlet totalWeight = 0;\n\n// Instagram scoring\nif (socialStats.instagram && !socialStats.instagram.error) {\n scores.instagram = calculatePlatformScore(socialStats.instagram, 'instagram');\n if (scores.instagram) {\n weightedScore += scores.instagram.total * SCORING_CONFIG.platform_weights.instagram;\n totalWeight += SCORING_CONFIG.platform_weights.instagram;\n }\n}\n\n// YouTube scoring \nif (socialStats.youtube && !socialStats.youtube.error) {\n scores.youtube = calculatePlatformScore(socialStats.youtube, 'youtube');\n if (scores.youtube) {\n weightedScore += scores.youtube.total * SCORING_CONFIG.platform_weights.youtube;\n totalWeight += SCORING_CONFIG.platform_weights.youtube;\n }\n}\n\nconst overallScore = totalWeight > 0 ? Math.round(weightedScore / totalWeight) : 0;\n\n// Status determination\nconst totalFollowers = (socialStats.instagram?.followers || 0) + (socialStats.youtube?.subscribers || 0);\nconst followersPerDollar = totalFollowers / (data.rate_card || 1);\n\nlet status = 'rejected_low_score';\nlet rejection_reason = '';\n\nif (totalFollowers < 5000) {\n status = 'rejected_insufficient_reach';\n rejection_reason = 'Total audience below 5K minimum';\n} else if (data.rate_card > 2000 && followersPerDollar < 100) {\n status = 'rejected_overpriced';\n rejection_reason = 'Rate card too high for audience size';\n} else if (overallScore >= 80) {\n status = 'approved';\n} else if (overallScore >= 65) {\n status = 'pending_review';\n} else {\n status = 'rejected_low_score';\n rejection_reason = `Score ${overallScore}/100 below threshold`;\n}\n\nreturn [{\n json: {\n ...data,\n scoring: {\n platform_scores: scores,\n overall_score: overallScore,\n total_followers: totalFollowers,\n followers_per_dollar: Math.round(followersPerDollar),\n calculated_at: new Date().toISOString()\n },\n status: status,\n rejection_reason: rejection_reason || null\n }\n}];"
},
"typeVersion": 2
},
{
"id": "dc6b665b-58de-409b-9dde-e3c7fe442c70",
"name": "Condition",
"type": "n8n-nodes-base.if",
"position": [
2032,
-16
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "d48efcf5-0146-4bea-82e4-66164aefa314",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{$json.status}}",
"rightValue": "approved"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "f1ba8012-bf02-4dac-91f6-165425a57f06",
"name": "Arrêt et erreur1",
"type": "n8n-nodes-base.stopAndError",
"position": [
2272,
144
],
"parameters": {
"errorMessage": "Engagement score doesn't meet the expectations"
},
"typeVersion": 1
},
{
"id": "0091470e-520c-4bb9-9172-fe66348f0137",
"name": "Ajout à la base de données approuvée",
"type": "n8n-nodes-base.googleSheets",
"position": [
2272,
-128
],
"parameters": {
"columns": {
"value": {
"Name": "={{$json.name}}",
"Email": "={{$json.email}}",
"niche": "={{ $json.niche }}",
"Status": "={{$json.status}}",
"YouTube": "={{$json.social_stats.youtube.username}}",
"Instagram": "=@{{$json.social_stats.instagram.username}}",
"Rate Card": "=${{$json.rate_card}}",
"Overall Score": "={{$json.scoring.overall_score}}",
"Total followers": "={{ $json.scoring.total_followers }}",
"Instagram Followers": "={{$json.social_stats.instagram.followers}}",
"YouTube Subscribers": "={{$json.social_stats.youtube.subscribers}}"
},
"schema": [
{
"id": "Name",
"type": "string",
"display": true,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "niche",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "niche",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Instagram",
"type": "string",
"display": true,
"required": false,
"displayName": "Instagram",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Instagram Followers",
"type": "string",
"display": true,
"required": false,
"displayName": "Instagram Followers",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "YouTube",
"type": "string",
"display": true,
"required": false,
"displayName": "YouTube",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "YouTube Subscribers",
"type": "string",
"display": true,
"required": false,
"displayName": "YouTube Subscribers",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Total followers",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Total followers",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Overall Score",
"type": "string",
"display": true,
"required": false,
"displayName": "Overall Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Rate Card",
"type": "string",
"display": true,
"required": false,
"displayName": "Rate Card",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MoHJiDjjw3EJGBS4YgbOcgeQ0oDYyrVLE2aVxTte1GY/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEETS_ID_HERE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1MoHJiDjjw3EJGBS4YgbOcgeQ0oDYyrVLE2aVxTte1GY/edit?usp=drivesdk",
"cachedResultName": "Add to Approved Database"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "aFQXpCszpua9MQeO",
"name": "Google Sheets account - Akshita"
}
},
"typeVersion": 4.7
},
{
"id": "95394f91-7907-4e96-b1bb-e12e4fe241e8",
"name": "Envoi de l'email de bienvenue",
"type": "n8n-nodes-base.gmail",
"position": [
2480,
-128
],
"webhookId": "f804aa4c-71f0-4f81-929a-a3c3d87430eb",
"parameters": {
"sendTo": "={{ $json.Email }}",
"message": "=Hi {{ $json.Name }},\n\nCongratulations! Your influencer application has been approved with an outstanding score of {{ $json['Overall Score'] }}/100.\n\nHere's what impressed us about your profile:\n- Instagram: {{ $json.Instagram }} with {{ $json['Instagram Followers'] }} engaged followers\n- YouTube: {{ $json.YouTube }} with {{ $json['YouTube Subscribers'] }} subscribers\n- Combined audience reach: {{ $json['Total followers'] }} across platforms\n- Strong engagement in the {{ $json.niche }} space\n\nWHAT'S NEXT:\n1. Our partnerships team will contact you within 24-48 hours\n2. We'll discuss campaign opportunities that match your content style\n3. You'll receive our brand guidelines and content requirements\n4. First campaign opportunities typically start within 1-2 weeks\n\nCAMPAIGN TYPES WE OFFER:\n- Sponsored posts and stories\n- Product collaborations\n- Long-term brand partnerships\n- Exclusive launch campaigns\n\nYour rate card of {{ $json['Rate Card'] }} per post fits well within our budget range for {{$json.niche}} creators.\n\nIf you have any questions before our team reaches out, feel free to reply to this email.\n\nWelcome to the [Your Brand Name] family!\n\nBest regards,\nThe [Your Brand Name] Influencer Team\n\n---\nBusiness Contact: partnerships@yourbrand.com\nThis is an automated message from our influencer management system.",
"options": {},
"subject": "Welcome to YOUR_BRAND_NAME - You're Approved!",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"id": "6XrYdrG9HaDZyzGH",
"name": "Gmail account - Akshita"
}
},
"typeVersion": 2.1
},
{
"id": "fda6ffae-e542-4c65-9b59-2ede839805c9",
"name": "Note adhésive",
"type": "n8n-nodes-base.stickyNote",
"position": [
-288,
-48
],
"parameters": {
"color": 7,
"width": 400,
"height": 400,
"content": "## WEBHOOK ENDPOINT\n\n**URL**: **/YOUR_CUSTOM_WEBHOOK_PATH**\nMethod: **POST**\nContent-Type: **application/json**\n\nTest payload:\n```{\n \"name\": \"Test User\",\n \"email\": \"test@example.com\", \n \"social_handles\": {\n \"instagram\": \"username\",\n \"youtube\": \"channelname\"\n },\n \"niche\": \"fitness\",\n \"country\": \"US\", \n \"rate_card\": 500\n}\n```"
},
"typeVersion": 1
},
{
"id": "7fe7b968-9b40-435c-9abc-aeeda1fc6c45",
"name": "Note adhésive1",
"type": "n8n-nodes-base.stickyNote",
"position": [
192,
-224
],
"parameters": {
"color": 7,
"width": 560,
"height": 384,
"content": "## REQUIRED FIELDS\n\n✓ name, email, social_handles\n✓ niche, country\n✓ Email format validation\n✓ Social handle cleanup\n\nMissing fields = **workflow stops**\n**Invalid email** = workflow stops"
},
"typeVersion": 1
},
{
"id": "f52e79de-92f2-44b7-8a6b-e0bfab2b1b15",
"name": "Note adhésive2",
"type": "n8n-nodes-base.stickyNote",
"position": [
848,
-272
],
"parameters": {
"color": 7,
"width": 304,
"height": 608,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n## API SETUP REQUIRED\n\n🔑 **RapidAPI Key**: Update in both nodes\n\n📊 **Instagram120** API\n📊 **YouTube138** API\n\nRate limits:\n- Add **2-3 sec** delays for production\n- Monitor quota usage\n- Have backup mock data ready\n\n"
},
"typeVersion": 1
},
{
"id": "9cba5934-8d84-4a8a-ac14-ef738a18f653",
"name": "Note adhésive3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1664,
-32
],
"parameters": {
"color": 7,
"width": 304,
"height": 464,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n## SCORING BREAKDOWN\n\n**Instagram**: 60% weight\n**YouTube**: 40% weight\n\nThresholds:\n- **80+** = Auto-approved\n- **65-79** = Manual review \n- **<65** = Auto-rejected\n\nAdditional checks:\n- **Min 5K** total followers\n- **Rate card** vs **audience ratio**"
},
"typeVersion": 1
},
{
"id": "0943217e-1983-4c7c-894c-53b7cf1801ad",
"name": "Note adhésive4",
"type": "n8n-nodes-base.stickyNote",
"position": [
2208,
-432
],
"parameters": {
"color": 7,
"width": 432,
"height": 480,
"content": "## APPROVED PATH ACTIONS\n\n1. Add to **Google Sheets** database\n2. Send **welcome email**\n3. Future: **Create Trello card**\n\n## PRODUCTION UPDATES NEEDED\n- **Replace YOUR_BRAND_NAME**\n- **Update Google Sheets ID**\n- **Set up email credentials**"
},
"typeVersion": 1
},
{
"id": "d6ae6ef3-ef78-46b4-86c2-9aad9d265b8e",
"name": "Note adhésive5",
"type": "n8n-nodes-base.stickyNote",
"position": [
2192,
128
],
"parameters": {
"color": 7,
"width": 288,
"height": 384,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n## REJECTION REASONS\n- Low engagement score\n- Insufficient total reach (<5K)\n- Overpriced rate card\n- Invalid email\n- Missing required data\n\nAll rejections logged for analysis"
},
"typeVersion": 1
},
{
"id": "b0753d3d-365e-45a6-bc2e-037c1bbf65e8",
"name": "Note adhésive6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1392,
512
],
"parameters": {
"color": 7,
"width": 304,
"height": 272,
"content": "## MONITORING CHECKLIST\n\n□ API quota usage tracking\n□ Webhook response times\n□ Email delivery rates\n□ Google Sheets write errors\n□ False positive/negative rates\n\nAdd Slack alerts for system failures\nWeekly performance review recommended"
},
"typeVersion": 1
},
{
"id": "4d1a7fc8-af75-4682-9567-a56b8c564e62",
"name": "Note adhésive7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-272,
448
],
"parameters": {
"color": 7,
"width": 320,
"height": 224,
"content": "## CREDENTIALS TO SETUP\n\n□ **VerifiEmail** API key\n□ **RapidAPI** key **(Instagram/YouTube)**\n□ **Google Sheets OAuth2**\n□ **Gmail OAuth2**\n\n⚠️ Delete old credential IDs before import\n⚠️ Test with real data before production"
},
"typeVersion": 1
},
{
"id": "e95556ec-f5c8-402d-b101-905523dd11dd",
"name": "Note adhésive8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-816,
-256
],
"parameters": {
"color": 7,
"width": 464,
"height": 672,
"content": "## AUTOMATED INFLUENCER CAMPAIGN MANAGEMENT SYSTEM\n\n**PURPOSE**: **Streamline influencer application processing** from form to approval\nFOR: **Marketing agencies, brands, influencer platforms with high application volume**\n\nWHAT IT DOES:\n- **Validates influencer applications automatically**\n- Fetches **real Instagram + YouTube** audience data \n- Scores **influencers using engagement + follower metrics**\n- Auto-approves qualified candidates\n- **Sends welcome emails** + adds to database\n- Rejects low-quality applications with reasons\n\nREQUIREMENTS:\n- **RapidAPI** subscription (Instagram/YouTube APIs)\n- **Google Sheets** for database\n- Email service (Gmail/SMTP)\n- n8n workflow platform\n\n## BUSINESS VALUE:\n- Saves **15-20 minutes** per application review\n- Consistent evaluation criteria\n- **24/7 automated processing**\n- Reduces manual screening workload by **80%**\n\n**CAPACITY**: Handles 100+ applications per day"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "e2fa68ce-ab34-459c-b0a9-cfad3ace15a7",
"connections": {
"dc6b665b-58de-409b-9dde-e3c7fe442c70": {
"main": [
[
{
"node": "0091470e-520c-4bb9-9172-fe66348f0137",
"type": "main",
"index": 0
}
],
[
{
"node": "f1ba8012-bf02-4dac-91f6-165425a57f06",
"type": "main",
"index": 0
}
]
]
},
"bebd9b90-7868-4c26-9eec-18fa9a4754c5": {
"main": [
[
{
"node": "867b3df2-09b1-459c-a619-12e30c753782",
"type": "main",
"index": 0
}
]
]
},
"afbbc1e1-76c2-4ca1-a75f-a7fe0946f130": {
"main": [
[
{
"node": "9a885214-eb51-4f09-92b6-92f202a28245",
"type": "main",
"index": 0
},
{
"node": "4a2298b1-e9a9-4667-8482-fd2580810c24",
"type": "main",
"index": 0
}
],
[
{
"node": "a01052ae-f470-44c9-bbd0-b9dc44e241c0",
"type": "main",
"index": 0
}
]
]
},
"12f8177d-3695-45f1-badb-4fd24c4e149c": {
"main": [
[
{
"node": "bb59a3b4-d17d-4eb0-b2de-26df8ea7fd6f",
"type": "main",
"index": 0
}
]
]
},
"62f128f9-6a68-4d78-baae-908153106221": {
"main": [
[
{
"node": "afbbc1e1-76c2-4ca1-a75f-a7fe0946f130",
"type": "main",
"index": 0
}
]
]
},
"bb59a3b4-d17d-4eb0-b2de-26df8ea7fd6f": {
"main": [
[
{
"node": "62f128f9-6a68-4d78-baae-908153106221",
"type": "main",
"index": 0
}
]
]
},
"0f58c1a3-b441-4e80-bc9a-010e4da46d2d": {
"main": [
[
{
"node": "bebd9b90-7868-4c26-9eec-18fa9a4754c5",
"type": "main",
"index": 1
}
]
]
},
"d77393c1-9fc2-45bc-9b13-b48f5c3593bf": {
"main": [
[
{
"node": "bebd9b90-7868-4c26-9eec-18fa9a4754c5",
"type": "main",
"index": 0
}
]
]
},
"4a2298b1-e9a9-4667-8482-fd2580810c24": {
"main": [
[
{
"node": "0f58c1a3-b441-4e80-bc9a-010e4da46d2d",
"type": "main",
"index": 0
}
]
]
},
"9a885214-eb51-4f09-92b6-92f202a28245": {
"main": [
[
{
"node": "d77393c1-9fc2-45bc-9b13-b48f5c3593bf",
"type": "main",
"index": 0
}
]
]
},
"0091470e-520c-4bb9-9172-fe66348f0137": {
"main": [
[
{
"node": "95394f91-7907-4e96-b1bb-e12e4fe241e8",
"type": "main",
"index": 0
}
]
]
},
"867b3df2-09b1-459c-a619-12e30c753782": {
"main": [
[
{
"node": "dc6b665b-58de-409b-9dde-e3c7fe442c70",
"type": "main",
"index": 0
}
]
]
}
}
}Comment utiliser ce workflow ?
Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.
Dans quelles scénarios ce workflow est-il adapté ?
Avancé - Création de contenu, IA Multimodale
Est-ce payant ?
Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.
Workflows recommandés
Jitesh Dugar
@jiteshdugarAI Automation Specialist - OpenAI, CRM & Automation Expert with a solid understanding of various tools that include Zapier, Make, Zoho CRM, Hubspot, Google Sheets, Airtable, Pipedrive, Google Analytics, and more.
Partager ce workflow