This workflow corresponds to n8n.io template #14264 — we link there as the canonical source.
This workflow follows the Agent → Emailsend recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "DjZZwIKloGiMV0fF",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Smart Next Trip Suggestion Engine with Claude AI and Behavioral Analysis",
"tags": [],
"nodes": [
{
"id": "eed08155-6530-4c87-ae0a-3d60b0266b71",
"name": "Main Documentation",
"type": "n8n-nodes-base.stickyNote",
"position": [
-272,
-304
],
"parameters": {
"width": 1072,
"height": 1554,
"content": "## Smart Next Trip Suggestion Engine with Claude AI\n\nThis workflow provides personalized travel destination recommendations by analyzing past trip history, user preferences, travel behavior patterns, and current trends. It uses Claude AI to generate intelligent, context-aware suggestions tailored to each traveler.\n\n### How it works\n\n1. **Receive Trip Request** - Webhook captures user query with preferences and constraints\n2. **Validate Input** - Checks required fields, normalizes data, calculates user profile metrics\n3. **Fetch Travel History** - Retrieves past trips, ratings, and behavioral data from Google Sheets\n4. **Analyze Patterns** - Identifies travel patterns, preferred destinations, seasonal preferences\n5. **Claude AI Recommendation** - Generates personalized destination suggestions with reasoning\n6. **Enrich with Live Data** - Adds current weather, events, flight prices (optional)\n7. **Store Recommendation** - Saves suggestion to database with full context\n8. **Send Personalized Response** - Delivers recommendations via email or API response\n9. **Daily Batch Updates** - Scheduled job to refresh recommendations for all active users\n10. **Trend Analysis** - Weekly reports on popular destinations and emerging trends\n\n### Setup Steps\n\n1. Import workflow into n8n\n2. Configure credentials:\n - **Anthropic API** - Claude AI for recommendation engine\n - **Google Sheets** - Trip history and user profiles\n - **SMTP / Gmail** - Email notifications\n - **Weather API** (optional) - Real-time weather data\n - **Flight API** (optional) - Price comparisons\n3. Create Google Sheets with tabs:\n - `user_profiles` - User data and preferences\n - `trip_history` - Past trip records\n - `recommendations` - Generated suggestions\n - `analytics` - Trend analysis logs\n4. Set your API keys and sheet IDs in the configuration nodes\n5. Activate both webhook and scheduled workflows\n\n### Sample Trip Request Payload\n```json\n{\n \"userId\": \"USER-2025-1234\",\n \"userName\": \"Sarah Johnson\",\n \"userEmail\": \"sarah.j@example.com\",\n \"preferences\": {\n \"budget\": \"moderate\",\n \"travelStyle\": \"adventure\",\n \"interests\": [\"hiking\", \"local cuisine\", \"cultural sites\"],\n \"climate\": \"warm\",\n \"duration\": \"7-10 days\",\n \"travelMonth\": \"June\"\n },\n \"constraints\": {\n \"maxBudget\": 3000,\n \"departureCity\": \"San Francisco\",\n \"companions\": \"solo\",\n \"accessibility\": \"none\"\n },\n \"excludeRegions\": [\"visited_recently\"],\n \"prioritize\": \"unique_experiences\"\n}\n```\n\n### Features\n- **AI-Powered Personalization** - Claude analyzes patterns and generates unique suggestions\n- **Behavioral Learning** - Improves over time based on trip ratings and feedback\n- **Real-Time Data Integration** - Weather, events, and pricing for recommended destinations\n- **Budget Optimization** - Suggests best value destinations within user budget\n- **Seasonal Intelligence** - Recommends optimal travel timing\n- **Trend Detection** - Identifies emerging destinations before they get crowded\n- **Multi-Factor Scoring** - Balances preferences, budget, timing, and uniqueness"
},
"typeVersion": 1
},
{
"id": "3682a8c4-1ca1-4508-b853-9cebd0ef35f3",
"name": "Section 1 Header",
"type": "n8n-nodes-base.stickyNote",
"position": [
1008,
192
],
"parameters": {
"color": 4,
"width": 460,
"height": 320,
"content": "## 1. Request Intake & Validation"
},
"typeVersion": 1
},
{
"id": "97ff4a42-d17f-4565-9635-5b02c171c9b9",
"name": "Section 2 Header",
"type": "n8n-nodes-base.stickyNote",
"position": [
1504,
48
],
"parameters": {
"color": 4,
"width": 840,
"height": 720,
"content": "## 2. History Analysis & AI Recommendation"
},
"typeVersion": 1
},
{
"id": "41ac0d32-1b96-4837-82b1-d799fe36899c",
"name": "Section 3 Header",
"type": "n8n-nodes-base.stickyNote",
"position": [
2384,
32
],
"parameters": {
"color": 4,
"width": 1456,
"height": 760,
"content": "## 3. Enrichment, Storage & Delivery"
},
"typeVersion": 1
},
{
"id": "ac59cdbd-824a-49e3-8ccc-f497ff18006b",
"name": "Section 4 Header",
"type": "n8n-nodes-base.stickyNote",
"position": [
1088,
880
],
"parameters": {
"color": 4,
"width": 1400,
"height": 380,
"content": "## 4. Daily Batch Recommendations & Trend Analysis"
},
"typeVersion": 1
},
{
"id": "750c4f35-49c5-4b44-b070-fcb53c822479",
"name": "Receive Trip Suggestion Request",
"type": "n8n-nodes-base.webhook",
"position": [
1088,
352
],
"parameters": {
"path": "trip-suggestion",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "c99f072c-a38e-4d44-8bc8-6d9757619087",
"name": "Validate and Normalize Request",
"type": "n8n-nodes-base.code",
"position": [
1312,
352
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Extract request body\nconst body = $input.item.json.body || $input.item.json;\n\n// Required field validation\nconst requiredFields = ['userId', 'userName', 'userEmail', 'preferences'];\nconst missing = requiredFields.filter(f => !body[f]);\nif (missing.length > 0) {\n throw new Error(`Missing required fields: ${missing.join(', ')}`);\n}\n\n// Validate email format\nconst emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nif (!emailRegex.test(body.userEmail)) {\n throw new Error(`Invalid email format: ${body.userEmail}`);\n}\n\n// Normalize preferences\nconst preferences = body.preferences || {};\nconst normalizedPrefs = {\n budget: (preferences.budget || 'moderate').toLowerCase(),\n travelStyle: (preferences.travelStyle || 'balanced').toLowerCase(),\n interests: Array.isArray(preferences.interests) ? preferences.interests : [],\n climate: (preferences.climate || 'any').toLowerCase(),\n duration: preferences.duration || '5-7 days',\n travelMonth: preferences.travelMonth || null\n};\n\n// Normalize constraints\nconst constraints = body.constraints || {};\nconst normalizedConstraints = {\n maxBudget: constraints.maxBudget || 5000,\n departureCity: constraints.departureCity || 'Not specified',\n companions: (constraints.companions || 'flexible').toLowerCase(),\n accessibility: constraints.accessibility || 'none'\n};\n\n// Calculate user profile score\nconst hasDetailedPrefs = normalizedPrefs.interests.length > 2;\nconst hasBudget = constraints.maxBudget > 0;\nconst hasTimeline = !!normalizedPrefs.travelMonth;\nconst profileCompleteness = Math.round(\n ((hasDetailedPrefs ? 40 : 0) + (hasBudget ? 30 : 0) + (hasTimeline ? 30 : 0))\n);\n\n// Build normalized request\nconst tripRequest = {\n // Identifiers\n requestId: `REQ-${Date.now()}-${Math.random().toString(36).substr(2, 9).toUpperCase()}`,\n userId: body.userId.trim(),\n userName: body.userName.trim(),\n userEmail: body.userEmail.trim().toLowerCase(),\n \n // Preferences\n preferences: normalizedPrefs,\n constraints: normalizedConstraints,\n \n // Exclusions and priorities\n excludeRegions: body.excludeRegions || [],\n excludeDestinations: body.excludeDestinations || [],\n prioritize: body.prioritize || 'balanced',\n \n // Metadata\n requestedAt: new Date().toISOString(),\n profileCompleteness,\n requestSource: body.requestSource || 'web_app',\n sessionId: body.sessionId || null,\n \n // Processing status\n status: 'VALIDATED'\n};\n\nreturn { json: { tripRequest } };"
},
"typeVersion": 2
},
{
"id": "4fde7100-c6a6-4363-8225-f0323a0dfdab",
"name": "Fetch User Travel History",
"type": "n8n-nodes-base.googleSheets",
"position": [
1616,
160
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "trip_history"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID_HERE"
},
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.5,
"continueOnFail": true
},
{
"id": "26325cc6-90af-43de-b8b9-7ec1c6b182f8",
"name": "Fetch User Profile Data",
"type": "n8n-nodes-base.googleSheets",
"position": [
1616,
352
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "user_profiles"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID_HERE"
},
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.5,
"continueOnFail": true
},
{
"id": "e0628839-f748-4109-a9a1-e70474ed0f01",
"name": "Analyze Travel Patterns",
"type": "n8n-nodes-base.code",
"position": [
1840,
272
],
"parameters": {
"jsCode": "// Get trip request and history\nconst tripRequest = $('Validate and Normalize Request').item.json.tripRequest;\nconst historyData = $('Fetch User Travel History').all().map(i => i.json);\nconst profileData = $('Fetch User Profile Data').all().map(i => i.json);\n\n// Filter user's trips\nconst userTrips = historyData.filter(t => t.userId === tripRequest.userId);\n\n// Analyze destination patterns\nconst destinationTypes = {};\nconst climatePrefs = {};\nconst budgetRanges = [];\nconst ratings = [];\nconst mostVisitedRegions = {};\n\nuserTrips.forEach(trip => {\n // Destination type analysis\n const type = trip.destinationType || 'unknown';\n destinationTypes[type] = (destinationTypes[type] || 0) + 1;\n \n // Climate preferences\n const climate = trip.climate || 'unknown';\n climatePrefs[climate] = (climatePrefs[climate] || 0) + 1;\n \n // Budget tracking\n if (trip.totalCost) budgetRanges.push(trip.totalCost);\n \n // Ratings\n if (trip.rating) ratings.push(trip.rating);\n \n // Regional preferences\n const region = trip.region || 'unknown';\n mostVisitedRegions[region] = (mostVisitedRegions[region] || 0) + 1;\n});\n\n// Calculate insights\nconst avgBudget = budgetRanges.length > 0 \n ? Math.round(budgetRanges.reduce((a, b) => a + b, 0) / budgetRanges.length)\n : 2000;\n\nconst avgRating = ratings.length > 0\n ? (ratings.reduce((a, b) => a + b, 0) / ratings.length).toFixed(1)\n : 'N/A';\n\nconst favoriteDestinationType = Object.keys(destinationTypes).sort(\n (a, b) => destinationTypes[b] - destinationTypes[a]\n)[0] || 'unknown';\n\nconst preferredClimate = Object.keys(climatePrefs).sort(\n (a, b) => climatePrefs[b] - climatePrefs[a]\n)[0] || 'any';\n\nconst topRegion = Object.keys(mostVisitedRegions).sort(\n (a, b) => mostVisitedRegions[b] - mostVisitedRegions[a]\n)[0] || 'none';\n\n// Recent trips (last 12 months)\nconst oneYearAgo = new Date();\noneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);\nconst recentTrips = userTrips.filter(t => {\n const tripDate = new Date(t.tripDate);\n return tripDate >= oneYearAgo;\n});\n\n// Build analysis\nconst travelAnalysis = {\n tripRequest,\n userStats: {\n totalTrips: userTrips.length,\n recentTrips: recentTrips.length,\n avgBudget,\n avgRating,\n favoriteDestinationType,\n preferredClimate,\n topRegion,\n travelFrequency: userTrips.length > 0 ? 'experienced' : 'new_traveler'\n },\n patterns: {\n destinationTypes,\n climatePrefs,\n mostVisitedRegions\n },\n recentDestinations: recentTrips.map(t => t.destination),\n highestRatedTrips: userTrips\n .filter(t => t.rating >= 4)\n .map(t => ({ destination: t.destination, rating: t.rating }))\n .slice(0, 5)\n};\n\nreturn [{ json: travelAnalysis }];"
},
"typeVersion": 2
},
{
"id": "12513851-331b-4f9c-82db-f8a00c44eeb6",
"name": "Claude AI Trip Recommendation Engine",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
2064,
272
],
"parameters": {
"text": "=You are an expert travel advisor with deep knowledge of global destinations, travel trends, cultural experiences, and optimal timing for visits worldwide.\n\nGenerate personalized trip recommendations for this traveler based on their profile, history, and preferences.\n\n**User Profile:**\n- User ID: {{ $json.tripRequest.userId }}\n- Name: {{ $json.tripRequest.userName }}\n- Travel Experience: {{ $json.userStats.travelFrequency }} ({{ $json.userStats.totalTrips }} total trips)\n- Average Budget: ${{ $json.userStats.avgBudget }}\n- Average Trip Rating: {{ $json.userStats.avgRating }}/5\n- Favorite Destination Type: {{ $json.userStats.favoriteDestinationType }}\n- Preferred Climate: {{ $json.userStats.preferredClimate }}\n- Most Visited Region: {{ $json.userStats.topRegion }}\n\n**Current Request:**\n- Budget Level: {{ $json.tripRequest.preferences.budget }}\n- Max Budget: ${{ $json.tripRequest.constraints.maxBudget }}\n- Travel Style: {{ $json.tripRequest.preferences.travelStyle }}\n- Interests: {{ $json.tripRequest.preferences.interests.join(', ') }}\n- Climate Preference: {{ $json.tripRequest.preferences.climate }}\n- Duration: {{ $json.tripRequest.preferences.duration }}\n- Travel Month: {{ $json.tripRequest.preferences.travelMonth || 'Flexible' }}\n- Departure City: {{ $json.tripRequest.constraints.departureCity }}\n- Companions: {{ $json.tripRequest.constraints.companions }}\n- Priority: {{ $json.tripRequest.prioritize }}\n\n**Recent Travel History:**\n{{ $json.recentDestinations.join(', ') || 'No recent trips' }}\n\n**Exclude:** {{ $json.tripRequest.excludeRegions.join(', ') || 'None' }}\n\n**Task:**\n1. Analyze the user's travel patterns and preferences\n2. Consider seasonality and optimal timing for the requested month\n3. Recommend 3-5 destinations that match their profile\n4. Balance familiarity vs. discovery based on their travel experience\n5. Ensure recommendations fit within budget constraints\n6. Provide specific reasoning for each suggestion\n7. Include insider tips and optimal timing\n\n**Response Format (JSON only, no markdown):**\n{\n \"recommendations\": [\n {\n \"destination\": \"City, Country\",\n \"region\": \"Geographic region\",\n \"matchScore\": 95,\n \"reasoning\": \"Why this destination fits the traveler's profile\",\n \"highlights\": [\"Key attraction 1\", \"Key attraction 2\", \"Key attraction 3\"],\n \"bestTimeToVisit\": \"Month range\",\n \"estimatedBudget\": 2500,\n \"budgetBreakdown\": {\"flights\": 600, \"accommodation\": 800, \"activities\": 700, \"food\": 400},\n \"travelStyle\": \"adventure\",\n \"climate\": \"warm\",\n \"culturalEvents\": [\"Festival or event if applicable\"],\n \"insiderTips\": [\"Local tip 1\", \"Local tip 2\"],\n \"similarToPastTrip\": \"Destination from history if applicable\",\n \"uniqueExperience\": \"What makes this different from past trips\",\n \"duration\": \"7-10 days\",\n \"difficultyLevel\": \"moderate\",\n \"crowdLevel\": \"moderate\",\n \"sustainabilityScore\": 8\n }\n ],\n \"overallStrategy\": \"Brief explanation of the recommendation strategy\",\n \"seasonalNote\": \"Any important seasonal considerations\",\n \"budgetOptimizationTips\": [\"How to maximize value within budget\"],\n \"alternativeMonths\": [\"Better months if requested month isn't optimal\"],\n \"confidenceScore\": 90,\n \"dataQualityNote\": \"Note on whether more trip history would improve recommendations\"\n}",
"options": {
"systemMessage": "You are an expert travel advisor. Respond with valid JSON only \u2014 no markdown, no code blocks, no preamble. Your recommendations must be personalized, budget-aware, and consider optimal timing."
},
"promptType": "define"
},
"typeVersion": 1.6
},
{
"id": "b5ad0e2a-b8d4-4644-96d8-06acfdef79bf",
"name": "Claude Sonnet 4 Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
2144,
496
],
"parameters": {
"model": "=claude-sonnet-4-20250514",
"options": {
"temperature": 0.3
}
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "564bf347-a2f9-4660-8a7c-9fae4845f828",
"name": "Parse AI Recommendations",
"type": "n8n-nodes-base.code",
"position": [
2416,
272
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const aiResponse = $input.item.json;\nlet aiText = aiResponse.response || aiResponse.output || aiResponse.text || '';\n\n// Handle Anthropic content array format\nif (aiResponse.content && Array.isArray(aiResponse.content)) {\n aiText = aiResponse.content[0]?.text || '';\n}\n\n// Strip markdown code blocks\nconst cleanText = aiText\n .replace(/```json\\s*/g, '')\n .replace(/```\\s*/g, '')\n .trim();\n\nlet recommendations;\ntry {\n recommendations = JSON.parse(cleanText);\n} catch (error) {\n throw new Error(`Failed to parse Claude response: ${error.message}. Raw: ${cleanText.substring(0, 200)}`);\n}\n\n// Get original request\nconst analysis = $('Analyze Travel Patterns').item.json;\nconst tripRequest = analysis.tripRequest;\n\n// Build final recommendation record\nconst recommendationRecord = {\n // Identifiers\n recommendationId: `REC-${Date.now()}-${Math.random().toString(36).substr(2, 9).toUpperCase()}`,\n requestId: tripRequest.requestId,\n userId: tripRequest.userId,\n userName: tripRequest.userName,\n userEmail: tripRequest.userEmail,\n \n // Recommendations\n destinations: recommendations.recommendations || [],\n topDestination: recommendations.recommendations?.[0]?.destination || 'None',\n topMatchScore: recommendations.recommendations?.[0]?.matchScore || 0,\n \n // Strategy and insights\n strategy: recommendations.overallStrategy || '',\n seasonalNote: recommendations.seasonalNote || '',\n budgetTips: recommendations.budgetOptimizationTips || [],\n alternativeMonths: recommendations.alternativeMonths || [],\n confidenceScore: recommendations.confidenceScore || 0,\n dataQualityNote: recommendations.dataQualityNote || '',\n \n // Request context\n requestedPreferences: tripRequest.preferences,\n requestedConstraints: tripRequest.constraints,\n userTravelStats: analysis.userStats,\n \n // Metadata\n generatedAt: new Date().toISOString(),\n aiModel: 'claude-sonnet-4-20250514',\n status: 'GENERATED',\n viewed: false,\n bookingsMade: 0\n};\n\nreturn { json: { recommendationRecord, fullRecommendations: recommendations } };"
},
"typeVersion": 2
},
{
"id": "ff6a17ec-58e3-469e-b979-e4114b87de07",
"name": "Wait for Data Enrichment",
"type": "n8n-nodes-base.wait",
"position": [
2640,
272
],
"parameters": {
"amount": 2
},
"typeVersion": 1.1
},
{
"id": "1b2ebd2d-6526-4f40-8199-a215b2d44a9b",
"name": "Enrich with Weather Data (Optional)",
"type": "n8n-nodes-base.httpRequest",
"position": [
2864,
144
],
"parameters": {
"url": "=https://api.openweathermap.org/data/2.5/weather?q={{ $json.recommendationRecord.topDestination }}&appid=YOUR_API_KEY&units=metric",
"options": {
"timeout": 5000
}
},
"typeVersion": 4.2,
"continueOnFail": true
},
{
"id": "727fc43c-ecf9-405a-971c-78db8998e5c0",
"name": "Store Recommendation Record",
"type": "n8n-nodes-base.googleSheets",
"position": [
2864,
352
],
"parameters": {
"columns": {
"value": {},
"mappingMode": "autoMapInputData"
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "recommendations"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID_HERE"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5,
"continueOnFail": true
},
{
"id": "de1783cc-b9de-45f1-99d1-188f0cb4278c",
"name": "Send Personalized Email",
"type": "n8n-nodes-base.emailSend",
"position": [
2864,
560
],
"parameters": {
"options": {},
"subject": "=Your Personalized Travel Recommendations - {{ $json.recommendationRecord.topDestination }} & More!",
"toEmail": "={{ $json.recommendationRecord.userEmail }}",
"fromEmail": "user@example.com"
},
"credentials": {
"smtp": {
"name": "<your credential>"
}
},
"typeVersion": 2.1,
"continueOnFail": true
},
{
"id": "359dcc6c-911b-4b38-84fa-3c77565193c1",
"name": "Build API Response",
"type": "n8n-nodes-base.code",
"position": [
3088,
400
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const data = $('Parse AI Recommendations').item.json;\nconst record = data.recommendationRecord;\nconst full = data.fullRecommendations;\n\nreturn {\n json: {\n success: true,\n recommendationId: record.recommendationId,\n userId: record.userId,\n generatedAt: record.generatedAt,\n topDestination: record.topDestination,\n totalRecommendations: record.destinations.length,\n confidenceScore: record.confidenceScore,\n recommendations: full.recommendations.map(r => ({\n destination: r.destination,\n region: r.region,\n matchScore: r.matchScore,\n estimatedBudget: r.estimatedBudget,\n bestTimeToVisit: r.bestTimeToVisit,\n highlights: r.highlights.slice(0, 3),\n insiderTips: r.insiderTips.slice(0, 2)\n })),\n strategy: full.overallStrategy,\n budgetTips: full.budgetOptimizationTips,\n message: `Found ${record.destinations.length} perfect destinations for you! Check your email for full details.`\n }\n};"
},
"typeVersion": 2
},
{
"id": "960e0cae-528b-4f8c-9243-3ec86ce761f7",
"name": "Wait Before Response",
"type": "n8n-nodes-base.wait",
"position": [
3312,
400
],
"parameters": {
"amount": 1
},
"typeVersion": 1.1
},
{
"id": "b25b1fc2-024b-462d-82f0-ad8d37c6074d",
"name": "Send Trip Recommendations Response",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
3536,
400
],
"parameters": {
"options": {
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json, null, 2) }}"
},
"typeVersion": 1
},
{
"id": "d9950974-bd7a-4050-9dca-ffc2fa946e3a",
"name": "Daily Batch Recommendation Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
1136,
1040
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * *"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "45c7cf39-7c7b-4ce9-9898-20398168361f",
"name": "Fetch All Active Users",
"type": "n8n-nodes-base.googleSheets",
"position": [
1360,
1040
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "user_profiles"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID_HERE"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "4c53076f-53bf-4bc7-89c3-db5909f0a2fa",
"name": "Analyze Emerging Travel Trends",
"type": "n8n-nodes-base.code",
"position": [
1632,
1040
],
"parameters": {
"jsCode": "const users = $input.all().map(i => i.json);\nconst today = new Date();\n\n// Filter users who need updated recommendations\nconst needsUpdate = users.filter(u => {\n if (!u.lastRecommendationDate) return true;\n const lastRec = new Date(u.lastRecommendationDate);\n const daysSince = Math.floor((today - lastRec) / (1000 * 60 * 60 * 24));\n return daysSince >= 7; // Weekly refresh\n});\n\n// Aggregate trending preferences\nconst trendingDestinations = {};\nconst popularStyles = {};\nconst budgetRanges = {};\n\nusers.forEach(u => {\n if (u.recentSearches) {\n u.recentSearches.forEach(s => {\n trendingDestinations[s] = (trendingDestinations[s] || 0) + 1;\n });\n }\n if (u.travelStyle) {\n popularStyles[u.travelStyle] = (popularStyles[u.travelStyle] || 0) + 1;\n }\n if (u.typicalBudget) {\n const range = u.typicalBudget < 2000 ? 'budget' : u.typicalBudget < 4000 ? 'moderate' : 'luxury';\n budgetRanges[range] = (budgetRanges[range] || 0) + 1;\n }\n});\n\nconst report = {\n reportDate: today.toISOString(),\n totalUsers: users.length,\n usersNeedingUpdate: needsUpdate.length,\n trends: {\n topDestinations: Object.entries(trendingDestinations)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n .map(([dest, count]) => ({ destination: dest, searches: count })),\n popularStyles: Object.entries(popularStyles)\n .sort((a, b) => b[1] - a[1])\n .map(([style, count]) => ({ style, users: count })),\n budgetDistribution: budgetRanges\n },\n usersToUpdate: needsUpdate.map(u => ({\n userId: u.userId,\n email: u.email,\n lastUpdate: u.lastRecommendationDate || 'never'\n }))\n};\n\nreturn [{ json: report }];"
},
"typeVersion": 2
},
{
"id": "15375291-be71-4c43-b24e-1cefad3b7db5",
"name": "Send Weekly Trend Report",
"type": "n8n-nodes-base.emailSend",
"position": [
1888,
1040
],
"parameters": {
"options": {},
"subject": "=Weekly Travel Trends Report - {{ new Date().toDateString() }}",
"toEmail": "user@example.com",
"fromEmail": "user@example.com"
},
"credentials": {
"smtp": {
"name": "<your credential>"
}
},
"typeVersion": 2.1,
"continueOnFail": true
},
{
"id": "a82bd246-24a8-46aa-8e30-b2b431ea25bf",
"name": "Log Analytics to Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
2192,
1040
],
"parameters": {
"columns": {
"value": {},
"mappingMode": "autoMapInputData"
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "analytics"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_ID_HERE"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "bd60eea4-a0d6-4d1e-a276-7efeaab66570",
"connections": {
"Build API Response": {
"main": [
[
{
"node": "Wait Before Response",
"type": "main",
"index": 0
}
]
]
},
"Wait Before Response": {
"main": [
[
{
"node": "Send Trip Recommendations Response",
"type": "main",
"index": 0
}
]
]
},
"Claude Sonnet 4 Model": {
"ai_languageModel": [
[
{
"node": "Claude AI Trip Recommendation Engine",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Fetch All Active Users": {
"main": [
[
{
"node": "Analyze Emerging Travel Trends",
"type": "main",
"index": 0
}
]
]
},
"Analyze Travel Patterns": {
"main": [
[
{
"node": "Claude AI Trip Recommendation Engine",
"type": "main",
"index": 0
}
]
]
},
"Fetch User Profile Data": {
"main": [
[
{
"node": "Analyze Travel Patterns",
"type": "main",
"index": 0
}
]
]
},
"Send Personalized Email": {
"main": [
[
{
"node": "Build API Response",
"type": "main",
"index": 0
}
]
]
},
"Parse AI Recommendations": {
"main": [
[
{
"node": "Wait for Data Enrichment",
"type": "main",
"index": 0
}
]
]
},
"Send Weekly Trend Report": {
"main": [
[
{
"node": "Log Analytics to Sheet",
"type": "main",
"index": 0
}
]
]
},
"Wait for Data Enrichment": {
"main": [
[
{
"node": "Enrich with Weather Data (Optional)",
"type": "main",
"index": 0
},
{
"node": "Store Recommendation Record",
"type": "main",
"index": 0
},
{
"node": "Send Personalized Email",
"type": "main",
"index": 0
}
]
]
},
"Fetch User Travel History": {
"main": [
[
{
"node": "Analyze Travel Patterns",
"type": "main",
"index": 0
}
]
]
},
"Store Recommendation Record": {
"main": [
[
{
"node": "Build API Response",
"type": "main",
"index": 0
}
]
]
},
"Analyze Emerging Travel Trends": {
"main": [
[
{
"node": "Send Weekly Trend Report",
"type": "main",
"index": 0
}
]
]
},
"Validate and Normalize Request": {
"main": [
[
{
"node": "Fetch User Travel History",
"type": "main",
"index": 0
},
{
"node": "Fetch User Profile Data",
"type": "main",
"index": 0
}
]
]
},
"Receive Trip Suggestion Request": {
"main": [
[
{
"node": "Validate and Normalize Request",
"type": "main",
"index": 0
}
]
]
},
"Daily Batch Recommendation Trigger": {
"main": [
[
{
"node": "Fetch All Active Users",
"type": "main",
"index": 0
}
]
]
},
"Enrich with Weather Data (Optional)": {
"main": [
[
{
"node": "Build API Response",
"type": "main",
"index": 0
}
]
]
},
"Claude AI Trip Recommendation Engine": {
"main": [
[
{
"node": "Parse AI Recommendations",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
anthropicApigoogleApigoogleSheetsOAuth2Apismtp
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow provides personalized travel destination recommendations by analyzing past trip history, user preferences, travel behavior patterns, and current trends. It uses Claude AI to generate intelligent, context-aware suggestions tailored to each traveler. Receive Trip…
Source: https://n8n.io/workflows/14264/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Automatically transforms your travel photos and notes into beautiful journals, highlight reels, and review drafts using Claude's vision and language capabilities. Trip Completion Trigger - Webhook or
This workflow continuously monitors CVE databases, threat intelligence feeds, and public security advisories to surface emerging zero-day threats, correlates them against your registered infrastructur
This workflow provides real-time detection of ransomware encryption patterns using Claude AI, with automated system isolation and incident response. File System Monitoring - Continuously monitors file
This workflow monitors active construction projects in real time, ingests weather forecasts, supplier delivery statuses, and crew/resource availability, then uses Claude AI to predict delay risk, esti
This workflow automates pre-dispatch customs document validation for international shipments. It ingests shipping document packages, extracts content from each file, uses Claude AI to cross-validate a