This workflow corresponds to n8n.io template #15015 — we link there as the canonical source.
This workflow follows the Google Drive → HTTP Request 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": "kPEtqTj6s9g3EEJX",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Conversational Trip Memory Search Engine",
"tags": [],
"nodes": [
{
"id": "913d1fe9-6b36-477e-a74a-cae9cc996a89",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"position": [
96,
464
],
"parameters": {
"path": "trip-search",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 1.1
},
{
"id": "73060b75-b123-4186-a6c1-dd96fa091b9b",
"name": "Welcome Guide",
"type": "n8n-nodes-base.stickyNote",
"position": [
-784,
-624
],
"parameters": {
"width": 520,
"height": 1496,
"content": "## \ud83d\uddfa\ufe0f Conversational Trip Memory Search Engine\n### Natural Language Travel History Search System\n\n**What This Does:**\nSearch your past trips using natural language queries like:\n- \"Show my Goa hotel from last year\"\n- \"Where did I stay in Paris?\"\n- \"Find my beach trips from 2024\"\n- \"Show all Italy restaurants I visited\"\n\n**How It Works:**\n1. User sends natural language query\n2. AI extracts search parameters (location, date, type)\n3. Searches across multiple data sources\n4. AI enriches results with context\n5. Returns formatted memories with photos & details\n\n**Data Sources:**\n\ud83d\udce7 Gmail (booking confirmations)\n\ud83d\udcc5 Google Calendar (trip events)\n\ud83d\udcb3 Expense tracking (receipts)\n\ud83d\udcf8 Google Photos (trip images)\n\ud83d\uddfa\ufe0f Google Maps (location history)\n\n**Advanced Features:**\n\u23f1\ufe0f 3 Strategic wait nodes\n\ud83e\udde0 AI-powered query understanding\n\ud83d\udd0d Multi-source data fusion\n\ud83d\udcca Intelligent ranking & sorting\n\ud83c\udfa8 Rich response formatting\n\n**Use Cases:**\n- Find old booking confirmations\n- Remember restaurant names\n- Retrieve travel documents\n- Create trip summaries\n- Share travel memories\n\n## \ud83d\udcca Monitoring & Analytics\n\n**Search Logs:**\n- All queries saved to Google Drive\n- Track popular searches\n- Identify data gaps\n- Improve AI parsing\n\n**Metrics:**\n- Search success rate\n- Average response time\n- Data source coverage\n- User satisfaction\n\n**Performance:**\n- API call optimization\n- Cache frequently searched trips\n- Reduce wait times\n- Improve relevance\n\n**Future Enhancements:**\n- Voice search support\n- Multi-language queries\n- Automatic trip summaries\n- Share memories feature\n- Trip comparison tool"
},
"typeVersion": 1
},
{
"id": "89608bfe-b422-4541-82d8-5dd94419e028",
"name": "Extract Query",
"type": "n8n-nodes-base.code",
"position": [
368,
464
],
"parameters": {
"jsCode": "const query = $input.item.json.body.query || '';\nconst userId = $input.item.json.body.userId || 'default_user';\n\nreturn {\n json: {\n originalQuery: query,\n userId: userId,\n timestamp: new Date().toISOString(),\n conversationId: `conv_${Date.now()}`\n }\n};"
},
"typeVersion": 2
},
{
"id": "0ee07f05-89d8-4988-a3d4-002b0cb9e20c",
"name": "AI Parse Query",
"type": "n8n-nodes-base.httpRequest",
"position": [
656,
464
],
"parameters": {
"url": "https://api.openai.com/v1/chat/completions",
"method": "POST",
"options": {},
"jsonBody": "={\n \"model\": \"gpt-4\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a travel query parser. Extract structured data from natural language travel queries. Return ONLY valid JSON with: location (string), dateRange (object with start/end), tripType (hotel/restaurant/activity/all), keywords (array).\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Parse this query: {{ $json.originalQuery }}\"\n }\n ],\n \"temperature\": 0.3\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "openAiApi"
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "a8668817-1443-473e-bc97-f2ae2f9bad99",
"name": "Structure Parameters",
"type": "n8n-nodes-base.code",
"position": [
928,
464
],
"parameters": {
"jsCode": "const aiResponse = $input.item.json.choices[0].message.content;\nconst parsed = JSON.parse(aiResponse.replace(/```json|```/g, '').trim());\n\nreturn {\n json: {\n searchParams: {\n location: parsed.location || '',\n dateStart: parsed.dateRange?.start || '',\n dateEnd: parsed.dateRange?.end || '',\n tripType: parsed.tripType || 'all',\n keywords: parsed.keywords || [],\n originalQuery: $input.item.json.originalQuery\n },\n userId: $input.item.json.userId,\n conversationId: $input.item.json.conversationId\n }\n};"
},
"typeVersion": 2
},
{
"id": "cf813c44-3f27-4b71-bdfe-476a4a56f792",
"name": "Stage 1 Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-16,
-240
],
"parameters": {
"color": 4,
"width": 832,
"height": 928,
"content": "## \ud83e\udde0 Stage 1: Query Understanding & Parsing\n\n**Purpose:**\nConvert natural language into structured search parameters.\n\n**Process:**\n1. Receive webhook query from user\n2. Extract user query and metadata\n3. Use GPT-4 to parse natural language\n4. Extract: location, dates, type, keywords\n5. Structure into searchable parameters\n\n**AI Extraction Examples:**\n\n**Query:** \"Show my Goa hotel from last year\"\n**Extracted:**\n- Location: \"Goa, India\"\n- Date: 2024-01-01 to 2024-12-31\n- Type: \"hotel\"\n- Keywords: [\"accommodation\", \"booking\"]\n\n**Query:** \"Paris restaurants in June\"\n**Extracted:**\n- Location: \"Paris, France\"\n- Date: 2024-06-01 to 2024-06-30\n- Type: \"restaurant\"\n- Keywords: [\"dining\", \"food\"]\n\n**Output:**\nStructured search object ready for multi-source querying"
},
"typeVersion": 1
},
{
"id": "ee9926f8-e112-4339-a646-7a2be15da2bc",
"name": "Search Gmail",
"type": "n8n-nodes-base.httpRequest",
"position": [
1328,
304
],
"parameters": {
"url": "https://gmail.googleapis.com/gmail/v1/users/me/messages",
"options": {},
"sendQuery": true,
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "=from:(booking.com OR airbnb.com OR hotels.com) {{ $json.searchParams.location }} after:{{ $json.searchParams.dateStart }} before:{{ $json.searchParams.dateEnd }}"
},
{
"name": "maxResults",
"value": "20"
}
]
},
"nodeCredentialType": "googleOAuth2Api"
},
"credentials": {
"googleOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "e742c699-6b41-45d2-a1dd-22561b5c6b63",
"name": "Search Calendar",
"type": "n8n-nodes-base.httpRequest",
"position": [
1328,
464
],
"parameters": {
"url": "https://www.googleapis.com/calendar/v3/calendars/primary/events",
"options": {},
"sendQuery": true,
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $json.searchParams.location }}"
},
{
"name": "timeMin",
"value": "={{ $json.searchParams.dateStart }}"
},
{
"name": "timeMax",
"value": "={{ $json.searchParams.dateEnd }}"
},
{
"name": "maxResults",
"value": "50"
}
]
},
"nodeCredentialType": "googleOAuth2Api"
},
"credentials": {
"googleOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "7365407f-4fa2-453f-bc1f-927b889da40e",
"name": "Search Photos",
"type": "n8n-nodes-base.httpRequest",
"position": [
1328,
624
],
"parameters": {
"url": "https://photoslibrary.googleapis.com/v1/mediaItems:search",
"options": {},
"jsonBody": "={\n \"filters\": {\n \"dateFilter\": {\n \"ranges\": [{\n \"startDate\": {\n \"year\": {{ $json.searchParams.dateStart.split('-')[0] }},\n \"month\": {{ $json.searchParams.dateStart.split('-')[1] }},\n \"day\": {{ $json.searchParams.dateStart.split('-')[2] }}\n },\n \"endDate\": {\n \"year\": {{ $json.searchParams.dateEnd.split('-')[0] }},\n \"month\": {{ $json.searchParams.dateEnd.split('-')[1] }},\n \"day\": {{ $json.searchParams.dateEnd.split('-')[2] }}\n }\n }]\n }\n }\n}",
"sendBody": true,
"sendQuery": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "pageSize",
"value": "25"
}
]
},
"nodeCredentialType": "googleOAuth2Api"
},
"credentials": {
"googleOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "43ca5299-2f50-42f2-8da9-7dae6850cbaf",
"name": "Wait 1 - API Cool Down",
"type": "n8n-nodes-base.wait",
"position": [
1616,
464
],
"parameters": {
"amount": 3
},
"typeVersion": 1.1
},
{
"id": "93d258a8-dd58-4f65-9ddd-3e5797426814",
"name": "Stage 2 Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
880,
-272
],
"parameters": {
"color": 6,
"width": 1132,
"height": 1040,
"content": "## \ud83d\udd0d Stage 2: Multi-Source Data Retrieval\n\n**Purpose:**\nSearch across all connected travel data sources simultaneously.\n\n**Data Sources:**\n\n**1. Gmail Search:**\n- Booking confirmations (Booking.com, Airbnb, Hotels.com)\n- Flight tickets (airlines)\n- Restaurant reservations (OpenTable, Resy)\n- Activity bookings (GetYourGuide, Viator)\n\n**2. Google Calendar:**\n- Trip events and itineraries\n- Hotel check-in/out dates\n- Restaurant reservations\n- Activity schedules\n\n**3. Google Photos:**\n- Photos from trip dates\n- Location-tagged images\n- Visual memories\n\n**Wait Node #1:**\n- **Duration:** 3 seconds\n- **Purpose:** API rate limit protection\n- **Why:** Prevents hitting Google API quotas\n\n**Output:**\nRaw data from all sources ready for fusion"
},
"typeVersion": 1
},
{
"id": "6e47bba0-186d-47e1-911c-b94d4124c7ff",
"name": "Merge All Sources",
"type": "n8n-nodes-base.merge",
"position": [
1888,
464
],
"parameters": {
"mode": "combine",
"options": {}
},
"typeVersion": 3
},
{
"id": "808c3849-91f2-4ce9-9a0c-1d802122d231",
"name": "Fuse Data",
"type": "n8n-nodes-base.code",
"position": [
2176,
464
],
"parameters": {
"jsCode": "const gmailData = $input.item.json.gmailResults || [];\nconst calendarData = $input.item.json.calendarResults || [];\nconst photosData = $input.item.json.photosResults || [];\nconst searchParams = $input.item.json.searchParams;\n\n// Combine and deduplicate data\nconst allResults = [\n ...gmailData.map(item => ({ source: 'gmail', type: 'booking', ...item })),\n ...calendarData.map(item => ({ source: 'calendar', type: 'event', ...item })),\n ...photosData.map(item => ({ source: 'photos', type: 'image', ...item }))\n];\n\n// Filter by relevance\nconst filtered = allResults.filter(item => {\n const itemText = JSON.stringify(item).toLowerCase();\n const location = searchParams.location.toLowerCase();\n return itemText.includes(location);\n});\n\nreturn {\n json: {\n results: filtered,\n totalFound: filtered.length,\n searchParams: searchParams,\n sources: {\n gmail: gmailData.length,\n calendar: calendarData.length,\n photos: photosData.length\n }\n }\n};"
},
"typeVersion": 2
},
{
"id": "365932ca-e446-4ca1-8c18-476efb7fb2df",
"name": "Wait 2 - Data Processing",
"type": "n8n-nodes-base.wait",
"position": [
2448,
464
],
"parameters": {
"amount": 2
},
"typeVersion": 1.1
},
{
"id": "1dad1cbb-4178-4f7c-8256-74ca66ed0d0c",
"name": "Stage 3 Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
2112,
-288
],
"parameters": {
"color": 4,
"width": 780,
"height": 1024,
"content": "## \ud83c\udfaf Stage 3: Data Fusion & Ranking\n\n**Purpose:**\nCombine results from all sources and rank by relevance.\n\n**Data Fusion Process:**\n1. Merge Gmail, Calendar, and Photos results\n2. Deduplicate entries (same hotel from multiple sources)\n3. Cross-reference data (match photos to bookings)\n4. Filter by search parameters\n5. Calculate relevance scores\n\n**Ranking Factors:**\n- Location match accuracy (90%)\n- Date range precision (85%)\n- Keyword relevance (75%)\n- Data completeness (booking + photos + calendar)\n- Recency (prefer recent trips)\n\n**Wait Node #2:**\n- **Duration:** 2 seconds\n- **Purpose:** Data processing buffer\n- **Why:** Allow time for complex data fusion\n\n**Enrichment:**\n- Link bookings to photos\n- Add map coordinates\n- Extract pricing info\n- Identify companions\n\n**Output:**\nRanked, enriched results ready for AI enhancement"
},
"typeVersion": 1
},
{
"id": "bdf76990-2dc5-4659-9fad-f7c1a9ec6b5e",
"name": "AI Enrich Response",
"type": "n8n-nodes-base.httpRequest",
"position": [
2736,
464
],
"parameters": {
"url": "https://api.anthropic.com/v1/messages",
"method": "POST",
"options": {},
"jsonBody": "={\n \"model\": \"claude-sonnet-4-20250514\",\n \"max_tokens\": 3000,\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Based on this search query: '{{ $json.searchParams.originalQuery }}' and these results: {{ JSON.stringify($json.results) }}, create a rich, conversational response. Include: 1) Direct answer to query, 2) Key details (hotel name, dates, price), 3) Related memories, 4) Suggestions for similar trips. Format as friendly conversation.\"\n }\n ]\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "anthropicApi"
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "7df0730e-0b78-4316-9901-42a39790c8eb",
"name": "Format Response",
"type": "n8n-nodes-base.code",
"position": [
3008,
464
],
"parameters": {
"jsCode": "const aiResponse = $input.item.json.content[0].text;\nconst results = $input.item.json.results || [];\nconst searchParams = $input.item.json.searchParams;\n\n// Format final response\nconst response = {\n success: true,\n conversationId: $input.item.json.conversationId,\n query: searchParams.originalQuery,\n answer: aiResponse,\n metadata: {\n totalResults: results.length,\n sources: $input.item.json.sources,\n searchParams: searchParams\n },\n results: results.slice(0, 10).map(r => ({\n title: r.title || r.summary || 'Trip Memory',\n date: r.date || r.startTime,\n location: r.location || searchParams.location,\n type: r.type,\n source: r.source,\n imageUrl: r.imageUrl || null,\n details: r.details || {}\n })),\n suggestions: [\n `Show more trips to ${searchParams.location}`,\n `Find photos from this trip`,\n `See all ${searchParams.tripType} bookings`\n ]\n};\n\nreturn { json: response };"
},
"typeVersion": 2
},
{
"id": "7297c74e-c1d0-4594-ba52-79549568ce80",
"name": "Wait 3 - Final Polish",
"type": "n8n-nodes-base.wait",
"position": [
3296,
464
],
"parameters": {
"amount": 1
},
"typeVersion": 1.1
},
{
"id": "e3a26551-2e8b-428b-92d6-0856713b2dd8",
"name": "Stage 4 Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
2976,
-416
],
"parameters": {
"color": 6,
"width": 820,
"height": 1184,
"content": "## \u2728 Stage 4: AI Enhancement & Response Formatting\n\n**Purpose:**\nUse AI to create conversational, context-rich responses.\n\n**AI Enhancement:**\n\n**Input:** Raw search results + user query\n**AI Tasks:**\n1. Understand user intent\n2. Create conversational answer\n3. Highlight key information\n4. Add context and memories\n5. Suggest related searches\n\n**Response Format:**\n```json\n{\n \"answer\": \"You stayed at The Taj in Goa from Dec 24-28, 2024...\",\n \"results\": [\n {\n \"title\": \"The Taj Hotel, Goa\",\n \"dates\": \"Dec 24-28, 2024\",\n \"price\": \"\u20b945,000\",\n \"photos\": 23,\n \"rating\": 4.8\n }\n ],\n \"suggestions\": [\"See Goa restaurant bookings\", \"View all beach trips\"]\n}\n```\n\n**Wait Node #3:**\n- **Duration:** 1 second\n- **Purpose:** Final response polishing\n- **Why:** Ensure clean delivery to user\n\n**Output:**\nBeautiful, conversational response ready for user"
},
"typeVersion": 1
},
{
"id": "cfabfb5c-c8df-421a-90ab-58a26398f471",
"name": "Return Response",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
3568,
464
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={{ JSON.stringify($json) }}"
},
"typeVersion": 1
},
{
"id": "1512e987-baa2-4df3-8f3f-69aaa92a439d",
"name": "Log to Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
3568,
624
],
"parameters": {
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "root",
"cachedResultName": "/ (Root folder)"
},
"operation": "createFromText"
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "5ef57942-68cf-45a6-98d2-1e2b41051417",
"connections": {
"Fuse Data": {
"main": [
[
{
"node": "Wait 2 - Data Processing",
"type": "main",
"index": 0
}
]
]
},
"Search Gmail": {
"main": [
[
{
"node": "Wait 1 - API Cool Down",
"type": "main",
"index": 0
}
]
]
},
"Extract Query": {
"main": [
[
{
"node": "AI Parse Query",
"type": "main",
"index": 0
}
]
]
},
"Search Photos": {
"main": [
[
{
"node": "Wait 1 - API Cool Down",
"type": "main",
"index": 0
}
]
]
},
"AI Parse Query": {
"main": [
[
{
"node": "Structure Parameters",
"type": "main",
"index": 0
}
]
]
},
"Format Response": {
"main": [
[
{
"node": "Wait 3 - Final Polish",
"type": "main",
"index": 0
}
]
]
},
"Search Calendar": {
"main": [
[
{
"node": "Wait 1 - API Cool Down",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger": {
"main": [
[
{
"node": "Extract Query",
"type": "main",
"index": 0
}
]
]
},
"Merge All Sources": {
"main": [
[
{
"node": "Fuse Data",
"type": "main",
"index": 0
}
]
]
},
"AI Enrich Response": {
"main": [
[
{
"node": "Format Response",
"type": "main",
"index": 0
}
]
]
},
"Structure Parameters": {
"main": [
[
{
"node": "Search Gmail",
"type": "main",
"index": 0
},
{
"node": "Search Calendar",
"type": "main",
"index": 0
},
{
"node": "Search Photos",
"type": "main",
"index": 0
}
]
]
},
"Wait 3 - Final Polish": {
"main": [
[
{
"node": "Return Response",
"type": "main",
"index": 0
},
{
"node": "Log to Drive",
"type": "main",
"index": 0
}
]
]
},
"Wait 1 - API Cool Down": {
"main": [
[
{
"node": "Merge All Sources",
"type": "main",
"index": 0
}
]
]
},
"Wait 2 - Data Processing": {
"main": [
[
{
"node": "AI Enrich Response",
"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.
anthropicApigoogleDriveOAuth2ApigoogleOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
What This Does: Search your past trips using natural language queries like: "Show my Goa hotel from last year" "Where did I stay in Paris?" "Find my beach trips from 2024" "Show all Italy restaurants I visited"
Source: https://n8n.io/workflows/15015/ — 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.
Automate short-term trading research by generating high-quality trade ideas using MCP (Market Context Protocol) signals and AI-powered analysis. 📈🤖 This workflow evaluates market context, catalysts, m
Most service businesses and freelancers track their quotes in Airtable (or something similar), but when it comes to actually sending the quote, they're still manually copying data into a document, exp
Automatically generates professional PDF invoices from webhook data and delivers them via email while storing backups in Google Drive. Perfect for freelancers, small businesses, and service providers
Email AI Auto-responder. Summerize and send email. Uses emailReadImap, emailSend, httpRequest, googleDrive. Event-driven trigger; 78 nodes.
Email AI Auto-responder. Summerize and send email. Uses emailReadImap, emailSend, httpRequest, googleDrive. Event-driven trigger; 78 nodes.