This workflow corresponds to n8n.io template #7991 — we link there as the canonical source.
This workflow follows the Google Sheets → 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "3c6136c1-c9e2-4645-98d7-736f0ac7606f",
"name": "When clicking 'Execute workflow'",
"type": "n8n-nodes-base.manualTrigger",
"position": [
144,
112
],
"parameters": {},
"typeVersion": 1
},
{
"id": "c42a5925-6485-477b-9339-e92d611c52cc",
"name": "URL Preprocessor",
"type": "n8n-nodes-base.code",
"position": [
592,
16
],
"parameters": {
"jsCode": "// URL Preprocessing - Fix domain formats and add protocols\nreturn $input.all().map(item => {\n let domain = item.json.Domain || \"\";\n \n // Clean up domain\n domain = domain.trim();\n \n // Add https:// if no protocol exists\n if (domain && !domain.startsWith('http://') && !domain.startsWith('https://')) {\n domain = 'https://' + domain;\n }\n \n // Remove trailing slashes\n domain = domain.replace(/\\/$/, '');\n \n return {\n ...item.json,\n Domain: domain,\n OriginalDomain: item.json.Domain\n };\n});"
},
"typeVersion": 2
},
{
"id": "c5938528-e3e1-4ad9-8104-3b0b3e584638",
"name": "Get row(s) in sheet1",
"type": "n8n-nodes-base.googleSheets",
"position": [
368,
16
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Tog_qW5NGJwCgk1t4_IpKC4rMurEx-tXuaapWgVli7w/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1Tog_qW5NGJwCgk1t4_IpKC4rMurEx-tXuaapWgVli7w",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Tog_qW5NGJwCgk1t4_IpKC4rMurEx-tXuaapWgVli7w/edit?usp=drivesdk",
"cachedResultName": "Technology Finder with Domain"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "f5cf9fac-ee4a-4986-8161-081cb5daaf60",
"name": "Split In Batches1",
"type": "n8n-nodes-base.splitInBatches",
"position": [
816,
16
],
"parameters": {
"options": {},
"batchSize": 5
},
"typeVersion": 3
},
{
"id": "704119a2-6e74-421b-ac12-76405e0d1e1a",
"name": "HTTP Request1",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"maxTries": 3,
"position": [
1040,
16
],
"parameters": {
"url": "={{$json['Domain']}}",
"options": {
"timeout": 20000,
"redirect": {
"redirect": {
"maxRedirects": 5
}
},
"response": {
"response": {
"responseFormat": "text",
"outputPropertyName": "html"
}
}
}
},
"retryOnFail": true,
"typeVersion": 4.2,
"alwaysOutputData": true
},
{
"id": "66488cb0-b9c0-4d72-8f45-f4e5cc642d3b",
"name": "Rate Limiting Wait1",
"type": "n8n-nodes-base.wait",
"position": [
1264,
16
],
"parameters": {
"unit": "seconds",
"amount": 2
},
"typeVersion": 1
},
{
"id": "13ea06c1-ae8a-46fc-8d71-4d0d9bc88d89",
"name": "Enhanced Technology Detection1",
"type": "n8n-nodes-base.code",
"position": [
1488,
16
],
"parameters": {
"jsCode": "//Enhanced Technology Detection with Proper Domain Extraction\n\nconst processItem = (item, index) => {\n try {\n console.log(`=== Processing Item ${index + 1} ===`);\n console.log('Item structure:', JSON.stringify(Object.keys(item), null, 2));\n console.log('Item.json keys:', item.json ? Object.keys(item.json) : 'No json property');\n \n // FIXED DOMAIN EXTRACTION - Multiple approaches for n8n compatibility\n let domain = \"Unknown Domain\";\n \n // Method 1: Direct domain field access (most common in n8n)\n if (item.json?.domain && typeof item.json.domain === 'string') {\n domain = item.json.domain.trim();\n console.log('Found domain in item.json.domain:', domain);\n }\n // Method 2: Capital D Domain field\n else if (item.json?.Domain && typeof item.json.Domain === 'string') {\n domain = item.json.Domain.trim();\n console.log('Found domain in item.json.Domain:', domain);\n }\n // Method 3: URL field that might contain domain\n else if (item.json?.url && typeof item.json.url === 'string') {\n domain = item.json.url.trim();\n console.log('Found domain in item.json.url:', domain);\n }\n // Method 4: Website field\n else if (item.json?.website && typeof item.json.website === 'string') {\n domain = item.json.website.trim();\n console.log('Found domain in item.json.website:', domain);\n }\n // Method 5: Site field\n else if (item.json?.site && typeof item.json.site === 'string') {\n domain = item.json.site.trim();\n console.log('Found domain in item.json.site:', domain);\n }\n // Method 6: Check if domain is passed alongside HTML data\n else if (item.json?.originalUrl && typeof item.json.originalUrl === 'string') {\n domain = item.json.originalUrl.trim();\n console.log('Found domain in item.json.originalUrl:', domain);\n }\n // Method 7: Extract from headers or metadata if available\n else if (item.json?.headers?.host) {\n domain = item.json.headers.host;\n console.log('Found domain in headers.host:', domain);\n }\n // Method 8: Look for any field that might contain domain info\n else {\n // Search through all fields for potential domain\n for (const [key, value] of Object.entries(item.json || {})) {\n if (typeof value === 'string' && \n !key.toLowerCase().includes('html') && \n !key.toLowerCase().includes('body') &&\n !key.toLowerCase().includes('content') &&\n !key.toLowerCase().includes('data') &&\n value.length < 200) {\n \n // Check if it looks like a domain\n if (value.includes('.') && \n !value.includes('<!DOCTYPE') && \n !value.includes('<html') &&\n (value.includes('http') || value.match(/^[a-zA-Z0-9][a-zA-Z0-9-]+\\.[a-zA-Z]{2,}/))) {\n domain = value.trim();\n console.log(`Found potential domain in item.json.${key}:`, domain);\n break;\n }\n }\n }\n }\n \n // Clean domain name (remove protocols, www, paths)\n if (domain && domain !== \"Unknown Domain\") {\n const originalDomain = domain;\n domain = domain\n .replace(/^https?:\\/\\//, '') // Remove protocol\n .replace(/^www\\./, '') // Remove www\n .replace(/\\/$/, '') // Remove trailing slash\n .split('/')[0] // Remove paths\n .split('?')[0] // Remove query params\n .split('#')[0]; // Remove fragments\n \n console.log(`Cleaned domain: ${originalDomain} -> ${domain}`);\n }\n \n // If still no domain found, try to extract from HTML meta tags\n if (domain === \"Unknown Domain\") {\n const html = item.json?.html || item.json?.data || item.json?.body || \"\";\n const ogUrlMatch = html.match(/<meta\\s+property=[\"']og:url[\"']\\s+content=[\"']([^\"']+)[\"']/i);\n const canonicalMatch = html.match(/<link\\s+rel=[\"']canonical[\"']\\s+href=[\"']([^\"']+)[\"']/i);\n \n if (ogUrlMatch && ogUrlMatch[1]) {\n domain = ogUrlMatch[1]\n .replace(/^https?:\\/\\//, '')\n .replace(/^www\\./, '')\n .split('/')[0];\n console.log('Extracted domain from og:url meta tag:', domain);\n } else if (canonicalMatch && canonicalMatch[1]) {\n domain = canonicalMatch[1]\n .replace(/^https?:\\/\\//, '')\n .replace(/^www\\./, '')\n .split('/')[0];\n console.log('Extracted domain from canonical link:', domain);\n }\n }\n \n console.log(`Final domain: ${domain}`);\n \n // Get HTML content for analysis\n const raw = item.json?.html || item.json?.data || item.json?.body || item.json?.content || \"\";\n const html = String(raw).toLowerCase();\n const originalHtml = String(raw);\n \n console.log(`HTML content length: ${raw.length}`);\n \n // Enhanced error checking with specific error types\n if (item.json?.error || !raw || raw.length < 100) {\n let specificError = \"Site unreachable\";\n let errorDetails = \"\";\n \n if (item.json?.error) {\n try {\n const errorStr = typeof item.json.error === 'object' ? \n JSON.stringify(item.json.error) : String(item.json.error);\n errorDetails = errorStr.substring(0, 100);\n \n if (errorStr.includes('ENOTFOUND')) {\n specificError = \"Domain not found (DNS error)\";\n } else if (errorStr.includes('ECONNREFUSED')) {\n specificError = \"Connection refused\";\n } else if (errorStr.includes('ETIMEDOUT') || errorStr.includes('timeout')) {\n specificError = \"Request timeout\";\n } else if (errorStr.includes('certificate') || errorStr.includes('CERT')) {\n specificError = \"SSL certificate error\";\n } else if (errorStr.includes('ECONNRESET')) {\n specificError = \"Connection reset\";\n } else if (errorStr.includes('404')) {\n specificError = \"Page not found (404)\";\n } else if (errorStr.includes('403')) {\n specificError = \"Access forbidden (403)\";\n } else if (errorStr.includes('500')) {\n specificError = \"Server error (500)\";\n }\n } catch (e) {\n errorDetails = \"Error parsing failed\";\n }\n } else if (item.json?.statusCode && item.json.statusCode >= 400) {\n specificError = `HTTP ${item.json.statusCode} error`;\n } else if (!raw) {\n specificError = \"No content received\";\n } else if (raw.length < 100) {\n specificError = \"Minimal content received\";\n }\n \n return {\n Domain: domain,\n Platform: \"Error - \" + specificError,\n Catalog: \"N/A\",\n Cart: \"N/A\",\n Checkout: \"N/A\",\n Wishlist: \"N/A\",\n PWA: \"N/A\",\n Payment_Gateway: \"N/A\",\n Framework: \"N/A\",\n Confidence_Score: \"0%\",\n Last_Checked: new Date().toISOString().split('T')[0],\n Remarks: `Error: ${specificError}${errorDetails ? ' - ' + errorDetails : ''}`\n };\n }\n \n // Initialize detection arrays\n const platforms = [];\n const frameworks = [];\n const paymentGateways = [];\n let cart = \"No\", catalog = \"No\", checkout = \"No\", wishlist = \"No\", pwa = \"No\";\n \n // Safe pattern matching function\n const has = (patterns) => {\n return patterns.some(pattern => {\n try {\n if (pattern instanceof RegExp) {\n return pattern.test(html) || pattern.test(originalHtml);\n }\n return html.includes(String(pattern).toLowerCase());\n } catch (e) {\n console.log(`Pattern matching error: ${e.message}`);\n return false;\n }\n });\n };\n \n // ========== ENHANCED PLATFORM DETECTION ==========\n \n // Magento (Enhanced detection)\n if (has([\n /x-magento-init/i,\n /mage\\/bootstrap/i,\n /static\\/version\\d+\\/frontend/i,\n /var\\s+BASE_URL\\s*=.*mage/i,\n /Mage\\.Cookies/i,\n \"form_key\",\n /magento\\s?enterprise/i,\n \"requirejs/require.js\",\n \"/static/frontend/\",\n \"magento\"\n ])) platforms.push(\"Magento\");\n \n // Shopify (Enhanced detection)\n if (has([\n /cdn\\.shopify\\.com/i,\n /assets\\.shopify\\.com/i,\n /checkout\\.shopify\\.com/i,\n /Shopify\\.theme/i,\n /window\\.ShopifyAnalytics/i,\n \"x-shopify\",\n \"/cart.js\",\n \"/products.json\",\n /generator[\"'][^>]*shopify/i\n ])) platforms.push(\"Shopify\");\n \n // WooCommerce (Enhanced detection)\n if (has([\n /wp-content\\/plugins\\/woocommerce/i,\n /woocommerce_params/i,\n /wc-cart-fragments/i,\n /class=\"[^\"]*woocommerce/i,\n /woocommerce-variation/i,\n \"woocommerce\",\n \"woocommerce-cart\"\n ])) platforms.push(\"WooCommerce\");\n \n // BigCommerce\n if (has([\n \"cdn.bcapp\",\n \"bigcommerce\",\n \"stencil-utils\",\n \"cornerstone\",\n /bigcommerce/i\n ])) platforms.push(\"BigCommerce\");\n \n // Custom E-commerce Detection (for sites like HSP Diesel)\n if (has([\n /add\\s+to\\s+cart/i,\n /shopping\\s+cart/i,\n /product\\s+details/i,\n /buy\\s+now/i,\n /add\\s+to\\s+bag/i,\n /purchase/i,\n /checkout/i,\n /price/i,\n /\\$[0-9,]+/,\n /product\\s+categories/i,\n /featured\\s+products/i,\n /new\\s+products/i,\n /online\\s+store/i,\n /e-?commerce/i\n ])) {\n if (platforms.length === 0) {\n platforms.push(\"Custom E-commerce\");\n }\n }\n \n // Other major platforms\n if (has([\"static.squarespace.com\", \"sqs-layout\", /generator[^>]*squarespace/i])) platforms.push(\"Squarespace\");\n if (has([\"wixstatic.com\", \"wix-code\", \"wixapps.net\", /generator[^>]*wix/i])) platforms.push(\"Wix\");\n if (has([\"webflow.js\", \"data-wf-site\", 'class=\"w-nav', /generator[^>]*webflow/i])) platforms.push(\"Webflow\");\n if (has([\"prestashop\", \"/modules/\", \"var prestashop\", 'class=\"ps-'])) platforms.push(\"PrestaShop\");\n if (has([\"index.php?route=\", \"catalog/view/theme/\", \"opencart\"])) platforms.push(\"OpenCart\");\n \n // Enterprise platforms\n if (has([\"demandware\", \"dwanalytics\", \"dwac\", \"checkout-begin\", \"sites-\", /salesforce.*commerce/i])) platforms.push(\"Salesforce Commerce Cloud\");\n if (has([\"suitecommerce\", \".ssp\", \"touchpoints\", \"scis\", /netsuite/i])) platforms.push(\"NetSuite SuiteCommerce\");\n if (has([/sap[.\\s]hybris/i, /oracle[.\\s]commerce/i, /ibm[.\\s]websphere/i])) platforms.push(\"Enterprise Commerce\");\n \n // Additional smaller platforms\n if (has([\"oscommerce\"])) platforms.push(\"osCommerce\");\n if (has([\"/mm5/\", \"miva merchant\", \"screen=plst\"])) platforms.push(\"Miva Merchant\");\n if (has([\"volusion\", \"/v/vspfiles/\", \"checkout.asp\"])) platforms.push(\"Volusion\");\n if (has([\"ecwid.min.js\", \"app.ecwid.com\", \"data-ecwid\"])) platforms.push(\"Ecwid\");\n if (has([\"nopcommerce\", /generator[^>]*nopcommerce/i])) platforms.push(\"nopCommerce\");\n \n // ========== FRAMEWORK DETECTION ==========\n if (has([\"next.js\", \"_next/\", /Next\\.js/i])) frameworks.push(\"Next.js\");\n if (has([\"nuxt.js\", \"_nuxt/\", /Nuxt\\.js/i])) frameworks.push(\"Nuxt.js\");\n if (has([/react/i, \"react.js\", \"react.min.js\"])) frameworks.push(\"React\");\n if (has([/vue\\.js/i, \"vue.min.js\"])) frameworks.push(\"Vue.js\");\n if (has([/angular/i, \"angular.js\"])) frameworks.push(\"Angular\");\n if (has([\"gatsby\", /gatsby/i])) frameworks.push(\"Gatsby\");\n if (has([\"wordpress\", \"wp-content\", \"wp-includes\"])) frameworks.push(\"WordPress\");\n \n // ========== PAYMENT GATEWAY DETECTION ==========\n if (has([\"stripe.js\", /stripe/i, \"js.stripe.com\"])) paymentGateways.push(\"Stripe\");\n if (has([\"paypal.js\", /paypal/i, \"paypal.com\"])) paymentGateways.push(\"PayPal\");\n if (has([\"square.js\", /square/i])) paymentGateways.push(\"Square\");\n if (has([\"klarna\", /klarna/i])) paymentGateways.push(\"Klarna\");\n if (has([\"razorpay\", /razorpay/i])) paymentGateways.push(\"Razorpay\");\n if (has([\"braintree\", /braintree/i])) paymentGateways.push(\"Braintree\");\n \n // ========== ENHANCED FEATURE DETECTION ==========\n \n // Cart Detection (Enhanced)\n if (has([\n /add[\\s\\-_]?to[\\s\\-_]?(cart|bag|basket)/i,\n /shopping[\\s\\-_]?cart/i,\n /mini[\\s\\-_]?cart/i,\n /cart[\\s\\-_]?total/i,\n /quantity[\\s\\-_]?selector/i,\n /buy[\\s\\-]?now/i,\n /order[\\s\\-]?now/i,\n /add[\\s\\-]?to[\\s\\-]?bag/i,\n /purchase/i,\n /cart\\.js/i,\n /shopping.*bag/i\n ])) cart = \"Yes\";\n \n // Catalog Detection (Enhanced)\n if (has([\n /catalog(ue)?/i,\n /product[\\s\\-_]?catalog/i,\n /category/i,\n /categories/i,\n /browse[\\s\\-_]?products/i,\n /product[\\s\\-_]?filter/i,\n /search[\\s\\-_]?results/i,\n /featured[\\s\\-_]?products/i,\n /new[\\s\\-_]?products/i,\n /top[\\s\\-_]?products/i,\n /popular[\\s\\-_]?products/i,\n /product[\\s\\-_]?bundles/i\n ])) catalog = \"Yes\";\n \n // Checkout Detection\n if (has([\n /checkout/i,\n /payment/i,\n /billing[\\s\\-_]?address/i,\n /shipping[\\s\\-_]?address/i,\n /place[\\s\\-_]?order/i,\n /complete[\\s\\-_]?purchase/i,\n /secure[\\s\\-_]?checkout/i,\n /proceed[\\s\\-_]?to[\\s\\-_]?checkout/i\n ])) checkout = \"Yes\";\n \n // Wishlist Detection\n if (has([\n /wish[\\s\\-_]?list/i,\n /save[\\s\\-_]?for[\\s\\-_]?later/i,\n /favorite/i,\n /add[\\s\\-_]?to[\\s\\-_]?wishlist/i\n ])) wishlist = \"Yes\";\n \n // PWA Detection\n if (has([\n \"service-worker\",\n \"manifest.json\",\n \"workbox\",\n /pwa/i,\n \"sw.js\"\n ])) pwa = \"Yes\";\n \n // ========== CONFIDENCE SCORING ==========\n let confidenceScore = 0;\n if (platforms.length > 0) confidenceScore += 40;\n if (cart === \"Yes\") confidenceScore += 20;\n if (checkout === \"Yes\") confidenceScore += 25;\n if (catalog === \"Yes\") confidenceScore += 10;\n if (paymentGateways.length > 0) confidenceScore += 5;\n \n confidenceScore = Math.min(confidenceScore, 100);\n \n // ========== REMARKS GENERATION ==========\n let remarks = \"Basic Website\";\n if (platforms.length || cart === \"Yes\" || catalog === \"Yes\" || checkout === \"Yes\") {\n remarks = \"E-commerce Features Detected\";\n } else if (frameworks.length) {\n remarks = \"Website Framework Detected\";\n } else if (html.length > 1000) {\n remarks = \"Website Active - No E-commerce Detected\";\n }\n \n console.log(`SUCCESS: ${domain} - ${platforms.join(', ')} - ${confidenceScore}%`);\n \n // Final output\n return {\n Domain: domain,\n Platform: platforms.length ? platforms.slice(0, 2).join(\"; \") : \"Not Detected\",\n Catalog: catalog,\n Cart: cart,\n Checkout: checkout,\n Wishlist: wishlist,\n PWA: pwa,\n Payment_Gateway: paymentGateways.length ? paymentGateways.slice(0, 2).join(\"; \") : \"Not Detected\",\n Framework: frameworks.length ? frameworks.slice(0, 2).join(\"; \") : \"Not Detected\",\n Confidence_Score: `${confidenceScore}%`,\n Last_Checked: new Date().toISOString().split('T')[0],\n Remarks: remarks\n };\n \n } catch (error) {\n console.log(`CRITICAL ERROR processing item ${index}:`, error.message);\n console.log('Error stack:', error.stack);\n \n // Try to at least get the domain even in error cases\n let errorDomain = \"Processing Error\";\n try {\n if (item.json?.domain) errorDomain = item.json.domain;\n else if (item.json?.Domain) errorDomain = item.json.Domain;\n else if (item.json?.url) errorDomain = item.json.url;\n else if (item.json?.website) errorDomain = item.json.website;\n } catch (e) {\n // Keep default error domain\n }\n \n return {\n Domain: errorDomain,\n Platform: \"Processing Error\",\n Catalog: \"N/A\",\n Cart: \"N/A\",\n Checkout: \"N/A\",\n Wishlist: \"N/A\",\n PWA: \"N/A\",\n Payment_Gateway: \"N/A\",\n Framework: \"N/A\",\n Confidence_Score: \"0%\",\n Last_Checked: new Date().toISOString().split('T')[0],\n Remarks: `Critical processing error: ${error.message}`\n };\n }\n};\n\n// Process all items with error tracking\ntry {\n const results = $input.all().map(processItem);\n console.log(`Successfully processed ${results.length} domains`);\n \n // Log summary of domains processed\n console.log('\\n=== PROCESSING SUMMARY ===');\n results.forEach((result, idx) => {\n console.log(`${idx + 1}. ${result.Domain} - Platform: ${result.Platform} - Score: ${result.Confidence_Score}`);\n });\n \n return results;\n} catch (globalError) {\n console.log('GLOBAL ERROR:', globalError.message);\n // Return minimal error response\n return [{\n Domain: \"Global Error\",\n Platform: \"Processing Error\",\n Catalog: \"N/A\",\n Cart: \"N/A\",\n Checkout: \"N/A\",\n Wishlist: \"N/A\",\n PWA: \"N/A\",\n Payment_Gateway: \"N/A\",\n Framework: \"N/A\",\n Confidence_Score: \"0%\",\n Last_Checked: new Date().toISOString().split('T')[0],\n Remarks: `Global processing error: ${globalError.message}`\n }];\n}"
},
"typeVersion": 2
},
{
"id": "b7982b69-1687-4fbc-8d72-25ab8ce75252",
"name": "Update Enhanced Results1",
"type": "n8n-nodes-base.googleSheets",
"position": [
1712,
16
],
"parameters": {
"columns": {
"value": {
"PWA": "={{ $json.PWA }}",
"Cart": "={{ $json.Cart }}",
"Domain": "={{ $json.Domain }}",
"Catalog": "={{ $json.Catalog }}",
"Remarks": "={{ $json.Remarks }}",
"Checkout": "={{ $json.Checkout }}",
"Platform": "={{ $json.Platform }}",
"Wishlist": "={{ $json.Wishlist }}",
"Framework": "={{ $json.Framework }}",
"row_number": 0,
"Last Checked": "={{ $json.Last_Checked }}",
"Payment Gateway": "={{ $json.Payment_Gateway }}",
"Confidence Score": "={{ $json.Confidence_Score }}"
},
"schema": [
{
"id": "Domain",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Domain",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Platform",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Platform",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Cart",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Cart",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Catalog",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Catalog",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Checkout",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Checkout",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Wishlist",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Wishlist",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "PWA",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "PWA",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Payment Gateway",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Payment Gateway",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Framework",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Framework",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Confidence Score",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Confidence Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Last Checked",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Last Checked",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Remarks",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Remarks",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Domain"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Tog_qW5NGJwCgk1t4_IpKC4rMurEx-tXuaapWgVli7w/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1Tog_qW5NGJwCgk1t4_IpKC4rMurEx-tXuaapWgVli7w",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Tog_qW5NGJwCgk1t4_IpKC4rMurEx-tXuaapWgVli7w/edit?usp=drivesdk",
"cachedResultName": "Technology Finder with Domain"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "2cb151c6-9e97-4542-92da-255eec3788d8",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
144,
-80
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "7d45c141-4fed-457f-adb7-132dbd7ad8ca",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
96,
-240
],
"parameters": {
"content": "Schedule a Cron from Schedule Trigger\n"
},
"typeVersion": 1
},
{
"id": "02895d34-8fc2-417e-8b45-f9d20b8defca",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
336,
208
],
"parameters": {
"content": "## Google Sheet\n \nCreate your google sheet and add domain column\n"
},
"typeVersion": 1
},
{
"id": "a7f94b2e-d79d-42f5-bc53-3194db1c8d9c",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1680,
192
],
"parameters": {
"content": "## Google update Sheet\n \nCreate your google sheet, add domain, Platform, etc. column\n"
},
"typeVersion": 1
}
],
"connections": {
"HTTP Request1": {
"main": [
[
{
"node": "Rate Limiting Wait1",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Get row(s) in sheet1",
"type": "main",
"index": 0
}
]
]
},
"URL Preprocessor": {
"main": [
[
{
"node": "Split In Batches1",
"type": "main",
"index": 0
}
]
]
},
"Split In Batches1": {
"main": [
[
{
"node": "HTTP Request1",
"type": "main",
"index": 0
}
],
[
{
"node": "HTTP Request1",
"type": "main",
"index": 0
}
]
]
},
"Rate Limiting Wait1": {
"main": [
[
{
"node": "Enhanced Technology Detection1",
"type": "main",
"index": 0
}
]
]
},
"Get row(s) in sheet1": {
"main": [
[
{
"node": "URL Preprocessor",
"type": "main",
"index": 0
}
]
]
},
"Enhanced Technology Detection1": {
"main": [
[
{
"node": "Update Enhanced Results1",
"type": "main",
"index": 0
}
]
]
},
"When clicking 'Execute workflow'": {
"main": [
[
{
"node": "Get row(s) in sheet1",
"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.
googleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
A production-ready n8n workflow that automatically analyzes websites to detect e-commerce platforms, frameworks, payment gateways, and technology stacks. Perfect for lead generation, competitive analysis, and market research.
Source: https://n8n.io/workflows/7991/ — 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.
TrackCollect_deeper. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 80 nodes.
This template is ideal for solo store owners, eCommerce marketers, automation beginners, or anyone using Shopify and Gmail who wants to recover lost revenue without coding.
PCN. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 60 nodes.
Product Ad Machine. Uses googleDrive, googleSheets, httpRequest, @ffmpeg-micro/n8n-nodes-ffmpeg-micro. Event-driven trigger; 60 nodes.
Basic AI SEO KW Research n8n DataForSEO Gumroad 030125. Uses googleSheets, googleDrive, httpRequest. Event-driven trigger; 56 nodes.