This workflow corresponds to n8n.io template #13994 — we link there as the canonical source.
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": "r3lMp8YtaKakgEp6",
"name": "AppSumo Lifetime Deal Monitor with ScrapeOps and Google Sheets",
"tags": [
{
"id": "Doq8CwkJgEUz5O8W",
"name": "AppSumo Deal Tracker",
"createdAt": "2026-03-10T07:27:04.779Z",
"updatedAt": "2026-03-10T07:27:04.779Z"
},
{
"id": "IzlHq5HmwX4xIIHt",
"name": "Lifetime Deal Monitor",
"createdAt": "2026-03-10T07:27:36.260Z",
"updatedAt": "2026-03-10T07:27:36.260Z"
},
{
"id": "Nabo4ItzmGCcNoDA",
"name": "SaaS Deal Tracking",
"createdAt": "2026-03-10T07:27:41.598Z",
"updatedAt": "2026-03-10T07:27:41.598Z"
},
{
"id": "lZKSh2IoxHklnOUw",
"name": "ScrapeOps",
"createdAt": "2025-10-20T20:27:13.410Z",
"updatedAt": "2025-10-20T20:27:13.410Z"
},
{
"id": "yzylwxvLF3YwGBRm",
"name": "Google Sheets Automation",
"createdAt": "2026-03-10T07:03:25.329Z",
"updatedAt": "2026-03-10T07:03:25.329Z"
}
],
"nodes": [
{
"id": "d1bad033-e9cb-45f7-b7de-03b88d3340c2",
"name": "Daily Schedule Trigger (09:00)",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
800,
512
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 9 * * *"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "bc66da17-e038-4442-9899-0ce0d04a4b72",
"name": "Fetch AppSumo Deals via ScrapeOps (JS Render)",
"type": "@scrapeops/n8n-nodes-scrapeops.ScrapeOps",
"position": [
1024,
512
],
"parameters": {
"url": "https://appsumo.com/browse/?tags=lifetime-deal",
"advancedOptions": {
"render_js": true
}
},
"typeVersion": 1
},
{
"id": "78501754-4e71-43f1-8c76-35ac809f86e8",
"name": "Parse AppSumo Deals HTML \u2192 Structured JSON",
"type": "n8n-nodes-base.code",
"position": [
1360,
512
],
"parameters": {
"jsCode": "// Parse AppSumo HTML to extract deals using String Splitting (Robust & No External Libs)\nconst item = items[0].json;\n// Extract HTML from ScrapeOps response - try multiple formats\nlet html = '';\n\n// ScrapeOps can return data in different formats\nif (typeof item === 'string') {\n html = item;\n} else if (item.response?.body) {\n html = item.response.body;\n} else if (item.body) {\n html = item.body;\n} else if (item.content) {\n html = item.content;\n} else if (item.data) {\n html = item.data;\n} else if (Array.isArray(item)) {\n // If it's an array, join it\n html = item.join('');\n} else {\n // Last resort - stringify and check\n const str = JSON.stringify(item);\n if (str.includes('<!DOCTYPE') || str.includes('<html')) {\n html = str;\n }\n}\n\nconst deals = [];\n\n// Split by the deal container identified in the HTML\n// Using a broader regex to catch variations in class spacing\nconst cardChunks = html.split(/class=[\"'][^\"']*relative h-full[^\"']*[\"']/i);\n\n// Skip the first chunk (header/nav)\nfor (let i = 1; i < cardChunks.length; i++) {\n const card = cardChunks[i];\n \n // Extract Title and URL\n const urlMatch = card.match(/href=[\"'](\\/products\\/[^\"']+)[\"']/i);\n const titleMatch = card.match(/<span class=[\"']sr-only[\"']>([^<]+)<\\/span>/i);\n \n if (urlMatch && titleMatch) {\n const url = `https://appsumo.com${urlMatch[1]}`;\n const title = titleMatch[1];\n \n // Image\n const imgMatch = card.match(/<img[^>]+src=[\"']([^\"']+)[\"']/i);\n const img = imgMatch ? imgMatch[1] : null;\n \n // Price\n const priceMatch = card.match(/id=[\"']deal-price[\"'][^>]*>([^<]+)</i);\n const currentPrice = priceMatch ? priceMatch[1].trim() : null;\n \n // Original Price\n const lastPriceMatch = card.match(/id=[\"']deal-price-original[\"'][^>]*>([^<]+)</i);\n const lastPrice = lastPriceMatch ? lastPriceMatch[1].trim() : null;\n \n // Discount Calculation\n let discount = null;\n if (currentPrice && lastPrice) {\n try {\n const curr = parseFloat(currentPrice.replace(/[^0-9.]/g, ''));\n const last = parseFloat(lastPrice.replace(/[^0-9.]/g, ''));\n if (last > 0) {\n const off = Math.round(((last - curr) / last) * 100);\n discount = `${off}% Off`;\n }\n } catch (e) {}\n }\n \n // Category\n // HTML: in<!-- --> <a ...>Productivity</a>\n // Regex needs to be loose about spaces and attributes\n const catMatch = card.match(/in<!-- -->\\s*<a[^>]*>([^<]+)<\\/a>/i);\n const category = catMatch ? catMatch[1].trim() : null;\n \n // Rating\n const ratingMatch = card.match(/alt=[\"']([0-9.]+)\\s*stars[\"']/i);\n const rating = ratingMatch ? ratingMatch[1] : null;\n \n // Reviews\n // HTML: <span>92<!-- --> reviews</span>\n const reviewsMatch = card.match(/<span>(\\d+)<!-- -->\\s*reviews<\\/span>/i);\n const reviewsCount = reviewsMatch ? reviewsMatch[1] : null;\n \n // Status\n let dealStatus = \"Active\";\n if (card.match(/Deal ends in/i)) dealStatus = \"Ending Soon\";\n if (card.match(/Sold Out/i)) dealStatus = \"Sold Out\";\n if (card.match(/Expired/i)) dealStatus = \"Expired\";\n\n deals.push({\n \"Product Name\": title,\n \"AppSumo URL\": url,\n \"Category\": category,\n \"Current Price\": currentPrice,\n \"Last Price\": lastPrice,\n \"Discount\": discount,\n \"Deal Status\": dealStatus,\n \"Rating\": rating,\n \"Reviews Count\": reviewsCount,\n \"Image\": img,\n \"scraped_at\": new Date().toISOString()\n });\n }\n}\n\nif (deals.length === 0) {\n return [{\n json: {\n \"Debug\": \"No deals found\",\n \"HTML Length\": html ? html.length : 0,\n \"Input Keys\": Object.keys(item),\n \"HTML Preview\": html ? html.substring(0, 500) : \"No HTML found\",\n \"Split Chunks\": cardChunks.length,\n \"Item Type\": typeof item,\n \"Is Array\": Array.isArray(item)\n }\n }];\n}\n\nreturn deals.map(deal => ({ json: deal }));"
},
"typeVersion": 2
},
{
"id": "cb136318-0c2b-4db8-be62-d0bb91e9522a",
"name": "Lookup Deal in Google Sheet (by URL)",
"type": "n8n-nodes-base.googleSheets",
"position": [
2032,
512
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "={{ $json[\"AppSumo URL\"] }}",
"lookupColumn": "AppSumo URL"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1L_Fn_wm55wc5EXi_ZIVmmXyFrz9nJ-29Xd71Ndz_XIk/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "https://docs.google.com/spreadsheets/d/1L_Fn_wm55wc5EXi_ZIVmmXyFrz9nJ-29Xd71Ndz_XIk/edit?usp=sharing"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4,
"continueOnFail": true
},
{
"id": "123561d8-ec1c-4c1e-9a1e-ca717dc85f24",
"name": "Merge Scrape + Existing Row (Enrich by URL)",
"type": "n8n-nodes-base.merge",
"position": [
2240,
512
],
"parameters": {
"mode": "combine",
"options": {
"fuzzyCompare": false,
"multipleMatches": "first",
"disableDotNotation": false
},
"joinMode": "enrichInput1",
"mergeByFields": {
"values": [
{
"field1": "AppSumo URL",
"field2": "AppSumo URL"
}
]
}
},
"typeVersion": 2.1
},
{
"id": "28505fc8-7c3d-45fc-bcb3-54125d32465e",
"name": "IF New Deal (Last Checked is empty)",
"type": "n8n-nodes-base.if",
"position": [
2480,
512
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json['Last Checked'] }}",
"operation": "isEmpty"
}
]
}
},
"typeVersion": 1
},
{
"id": "a87a44c2-7db6-4a15-b4bf-ed053b718002",
"name": "Stamp Last Checked (New Deal Path)",
"type": "n8n-nodes-base.code",
"position": [
2720,
416
],
"parameters": {
"jsCode": "// Prepare New Deal - Process ALL items\nconst output = [];\n\nfor (const item of items) {\n output.push({\n json: {\n ...item.json,\n 'Last Checked': new Date().toISOString()\n }\n });\n}\n\nreturn output;"
},
"typeVersion": 2
},
{
"id": "efb4c2a2-56b3-4305-8e54-dc21a627b22a",
"name": "Stamp Last Checked (Existing Deal Path)",
"type": "n8n-nodes-base.code",
"position": [
2720,
624
],
"parameters": {
"jsCode": "// Compare Existing Deal - Process ALL items\nconst output = [];\n\nfor (const item of items) {\n // Just update timestamp\n output.push({\n json: {\n ...item.json,\n 'Last Checked': new Date().toISOString()\n }\n });\n}\n\nreturn output;"
},
"typeVersion": 2
},
{
"id": "cf999433-15af-44cd-966b-07bc4664a1bb",
"name": "Append New Deal to Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
2928,
416
],
"parameters": {
"columns": {
"value": {
"Image": "={{ $json['Image'] }}",
"Rating": "={{ $json['Rating'] }}",
"Category": "={{ $json['Category'] }}",
"Discount": "={{ $json['Discount'] }}",
"Last Price": "={{ $json['Last Price'] }}",
"AppSumo URL": "={{ $json['AppSumo URL'] }}",
"Deal Status": "={{ $json['Deal Status'] }}",
"Last Checked": "={{ $json['Last Checked'] }}",
"Product Name": "={{ $json['Product Name'] }}",
"Current Price": "={{ $json['Current Price'] }}",
"Reviews Count": "={{ $json['Reviews Count'] }}"
},
"schema": [
{
"id": "Product Name",
"type": "string",
"display": true,
"required": false,
"displayName": "Product Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "AppSumo URL",
"type": "string",
"display": true,
"required": false,
"displayName": "AppSumo URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Category",
"type": "string",
"display": true,
"required": false,
"displayName": "Category",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Last Price",
"type": "string",
"display": true,
"required": false,
"displayName": "Last Price",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Current Price",
"type": "string",
"display": true,
"required": false,
"displayName": "Current Price",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Discount",
"type": "string",
"display": true,
"required": false,
"displayName": "Discount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Deal Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Deal Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Rating",
"type": "string",
"display": true,
"required": false,
"displayName": "Rating",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Reviews Count",
"type": "string",
"display": true,
"required": false,
"displayName": "Reviews Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Last Checked",
"type": "string",
"display": true,
"required": false,
"displayName": "Last Checked",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Change Detected",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Change Detected",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "New Deal",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "New Deal",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Image",
"type": "string",
"display": true,
"required": false,
"displayName": "Image",
"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/1L_Fn_wm55wc5EXi_ZIVmmXyFrz9nJ-29Xd71Ndz_XIk/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "https://docs.google.com/spreadsheets/d/1L_Fn_wm55wc5EXi_ZIVmmXyFrz9nJ-29Xd71Ndz_XIk/edit?usp=sharing"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4
},
{
"id": "74076d65-8611-4360-9591-65ef5c11bce1",
"name": "Update Existing Deal Row in Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
2928,
624
],
"parameters": {
"columns": {
"value": {
"Image": "={{ $json['Image'] }}",
"Rating": "={{ $json['Rating'] }}",
"Category": "={{ $json['Category'] }}",
"Discount": "={{ $json['Discount'] }}",
"Last Price": "={{ $json['Last Price'] }}",
"AppSumo URL": "={{ $json['AppSumo URL'] }}",
"Deal Status": "={{ $json['Deal Status'] }}",
"Last Checked": "={{ $json['Last Checked'] }}",
"Product Name": "={{ $json['Product Name'] }}",
"Current Price": "={{ $json['Current Price'] }}",
"Reviews Count": "={{ $json['Reviews Count'] }}"
},
"schema": [
{
"id": "Product Name",
"type": "string",
"display": true,
"required": false,
"displayName": "Product Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "AppSumo URL",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "AppSumo URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Category",
"type": "string",
"display": true,
"required": false,
"displayName": "Category",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Last Price",
"type": "string",
"display": true,
"required": false,
"displayName": "Last Price",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Current Price",
"type": "string",
"display": true,
"required": false,
"displayName": "Current Price",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Discount",
"type": "string",
"display": true,
"required": false,
"displayName": "Discount",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Deal Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Deal Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Rating",
"type": "string",
"display": true,
"required": false,
"displayName": "Rating",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Reviews Count",
"type": "string",
"display": true,
"required": false,
"displayName": "Reviews Count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Last Checked",
"type": "string",
"display": true,
"required": false,
"displayName": "Last Checked",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Change Detected",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Change Detected",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "New Deal",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "New Deal",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Image",
"type": "string",
"display": true,
"required": false,
"displayName": "Image",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"AppSumo URL"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1L_Fn_wm55wc5EXi_ZIVmmXyFrz9nJ-29Xd71Ndz_XIk/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "https://docs.google.com/spreadsheets/d/1L_Fn_wm55wc5EXi_ZIVmmXyFrz9nJ-29Xd71Ndz_XIk/edit?usp=sharing"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4
},
{
"id": "fdefa234-338b-4616-8e86-542e8cf22371",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"width": 688,
"height": 784,
"content": "# \ud83d\udecd\ufe0f AppSumo Lifetime Deal Monitor \u2192 Google Sheets\n\nThis workflow automatically tracks AppSumo lifetime deals daily. It fetches the AppSumo browse page using **ScrapeOps Proxy with JS rendering**, parses each deal into structured data, filters by your target categories, and saves new or updated deals to Google Sheets with full deduplication.\n\n### How it works\n1. \u23f0 **Daily Schedule Trigger** fires every day at 09:00 automatically.\n2. \ud83c\udf10 **Fetch AppSumo Deals via ScrapeOps** loads the browse page with JavaScript rendering enabled.\n3. \ud83d\udd0d **Parse AppSumo Deals HTML \u2192 Structured JSON** extracts name, URL, category, prices, discount, rating, reviews, image, and timestamps.\n4. \ud83d\udd0e **Filter Relevant Deal Categories** keeps only deals matching your target keywords.\n5. \ud83d\udccb **Lookup Deal in Google Sheet (by URL)** checks if the deal already exists in your sheet.\n6. \ud83d\udd00 **Merge Scrape + Existing Row** combines scraped data with any existing sheet row.\n7. \ud83d\udd00 **IF New Deal** routes new vs. existing deals to separate write paths.\n8. \ud83d\udcbe **Append New Deal to Sheet** adds a fresh row for new deals.\n9. \ud83d\udd04 **Update Existing Deal Row** refreshes pricing and status for known deals.\n\n### Setup steps\n- Register for a free ScrapeOps API key: https://scrapeops.io/app/register/n8n\n- Add ScrapeOps credentials in n8n. Docs: https://scrapeops.io/docs/n8n/overview/\n- [Duplicate the Google Sheet](https://docs.google.com/spreadsheets/d/1L_Fn_wm55wc5EXi_ZIVmmXyFrz9nJ-29Xd71Ndz_XIk/edit#gid=0\") and paste your Sheet URL into the Lookup, Append, and Update nodes.\n- Edit the category/keyword list in **Filter Relevant Deal Categories** to match your interests.\n- Run once manually to confirm, then activate.\n\n### Customization\n- Add Slack, Gmail, or Discord alerts on the **New Deal** path.\n- Change the schedule time in the trigger node to suit your timezone."
},
"typeVersion": 1
},
{
"id": "d4da614f-e5ca-4b2e-8062-49e840ff0e75",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
736,
400
],
"parameters": {
"color": 7,
"width": 496,
"height": 288,
"content": "## 1. Trigger & Fetch\nRuns daily at 09:00 and loads the AppSumo browse page via [ScrapeOps Proxy](https://scrapeops.io/docs/n8n/proxy-api/) with JavaScript rendering enabled."
},
"typeVersion": 1
},
{
"id": "3c8d58b5-7f66-46c2-9f65-259aa428abde",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1248,
400
],
"parameters": {
"color": 7,
"width": 336,
"height": 288,
"content": "## 2. Parse Deals\nExtracts title, URL, prices, discount, category, rating, reviews, image, status, and timestamps from the raw HTML into clean structured JSON."
},
"typeVersion": 1
},
{
"id": "7b2a13d0-3b48-427a-8cb2-51663953981a",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1600,
400
],
"parameters": {
"color": 7,
"width": 336,
"height": 288,
"content": "## 3. Filter by Category\nKeeps only deals that match your target categories or keywords. Edit the list inside this node to customize what gets tracked."
},
"typeVersion": 1
},
{
"id": "c65b592c-690c-4abe-be87-517ede20c410",
"name": "Filter Relevant Deal Categories",
"type": "n8n-nodes-base.code",
"position": [
1712,
512
],
"parameters": {
"jsCode": "// Filter for specific categories\nconst targetCategories = ['No-Code', 'Automation', 'AI', 'Productivity', 'Marketing'];\n\nreturn items.filter(item => {\n const category = item.json['Category'] || '';\n const title = item.json['Product Name'] || '';\n \n // Check if any target category is mentioned in tags or title\n const isRelevant = targetCategories.some(cat => \n category.toLowerCase().includes(cat.toLowerCase()) || \n title.toLowerCase().includes(cat.toLowerCase())\n );\n \n return isRelevant;\n});"
},
"typeVersion": 2
},
{
"id": "af8f272e-50e8-4b9f-8bda-8b4c8195b63b",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1952,
400
],
"parameters": {
"color": 7,
"width": 448,
"height": 288,
"content": "## 4. Deduplicate & Merge\nLooks up each deal by its AppSumo URL in Google Sheets, then merges scraped data with any existing row to enrich the record."
},
"typeVersion": 1
},
{
"id": "db326fc5-7633-4926-9658-5139bb6efbbc",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
2416,
320
],
"parameters": {
"color": 7,
"width": 784,
"height": 480,
"content": "## 5. Route & Write to Google Sheets\nNew deals are appended as fresh rows. Existing deals have their price, status, and timestamps updated in place."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "47b7f578-3c75-4173-bad1-0b4b064b6bd9",
"connections": {
"Daily Schedule Trigger (09:00)": {
"main": [
[
{
"node": "Fetch AppSumo Deals via ScrapeOps (JS Render)",
"type": "main",
"index": 0
}
]
]
},
"Filter Relevant Deal Categories": {
"main": [
[
{
"node": "Lookup Deal in Google Sheet (by URL)",
"type": "main",
"index": 0
},
{
"node": "Merge Scrape + Existing Row (Enrich by URL)",
"type": "main",
"index": 0
}
]
]
},
"Stamp Last Checked (New Deal Path)": {
"main": [
[
{
"node": "Append New Deal to Sheet",
"type": "main",
"index": 0
}
]
]
},
"IF New Deal (Last Checked is empty)": {
"main": [
[
{
"node": "Stamp Last Checked (New Deal Path)",
"type": "main",
"index": 0
}
],
[
{
"node": "Stamp Last Checked (Existing Deal Path)",
"type": "main",
"index": 0
}
]
]
},
"Lookup Deal in Google Sheet (by URL)": {
"main": [
[
{
"node": "Merge Scrape + Existing Row (Enrich by URL)",
"type": "main",
"index": 1
}
]
]
},
"Stamp Last Checked (Existing Deal Path)": {
"main": [
[
{
"node": "Update Existing Deal Row in Sheet",
"type": "main",
"index": 0
}
]
]
},
"Merge Scrape + Existing Row (Enrich by URL)": {
"main": [
[
{
"node": "IF New Deal (Last Checked is empty)",
"type": "main",
"index": 0
}
]
]
},
"Parse AppSumo Deals HTML \u2192 Structured JSON": {
"main": [
[
{
"node": "Filter Relevant Deal Categories",
"type": "main",
"index": 0
}
]
]
},
"Fetch AppSumo Deals via ScrapeOps (JS Render)": {
"main": [
[
{
"node": "Parse AppSumo Deals HTML \u2192 Structured JSON",
"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
This n8n template automates daily monitoring of AppSumo lifetime deals. Using ScrapeOps Proxy with JavaScript rendering to reliably fetch pages and a structured parsing pipeline, the workflow tracks new and updated deals — saving everything to Google Sheets with full…
Source: https://n8n.io/workflows/13994/ — 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.
This n8n template tracks GitHub Trending repositories (daily/weekly/monthly), parses the trending page into structured data (rank, repo name, stars, language, etc.), and stores results in Google Sheet
This workflow automates video distribution to 9 social platforms simultaneously using Blotato's API. It includes both a scheduled publisher (checks Google Sheets for videos marked "Ready") and a subwo
YogiAI. Uses googleSheets, googleSheetsTool, httpRequest, stopAndError. Scheduled trigger; 61 nodes.
This workflow monitors Google Calendar for events indicating that a customer will visit the company today or the next day, retrieves the required details, and sends reminder notifications to the relev
Useful if a team is working within a single instance and you want to be notified of what workflows have changed since you last visited them. Another use-case might be monitoring your managed instances