Algolia email verification with BillionVerify
Algolia powers fast, relevant search experiences across websites and applications. Many Algolia indices include user records with email addresses used for personalization, analytics, and communications. Keeping those email fields clean ensures search-driven features and downstream messaging work reliably.
Why verify before the send
User records indexed in Algolia often feed email campaigns, account lookups, and personalized recommendations. Invalid or disposable addresses in the index pollute search results, break user-matching logic, and cause bounce problems when those addresses are later used for outreach. BillionVerify validates emails at the point of entry, keeping your Algolia data accurate.
Ready-to-use n8n workflow
Import this workflow into n8n β it verifies every address with BillionVerify before Algolia sends, so only deliverable contacts are emailed. Install the BillionVerify community node first, then add your API key. Adapted from this n8n template
{
"name": "Automated weekly product promotion emails for e-commerce with Algolia and Gmail + BillionVerify",
"nodes": [
{
"id": "78ab8125-5275-4a17-8352-d466a5c7ea30",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-560,
-176
],
"parameters": {
"color": 4,
"height": 192,
"content": "## Every Week\nSends a weekly newsletter on Sundays at 8.00 am containing discounted products for the coming week"
},
"typeVersion": 1
},
{
"id": "4d2975d0-1b9d-4453-82f8-753383b97c3f",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
2768,
-208
],
"parameters": {
"color": 4,
"width": 256,
"height": 208,
"content": "## Send Newsletter to subscribers\nSend the the answer to the customer"
},
"typeVersion": 1
},
{
"id": "1847023a-0a17-4adf-b110-dfc84065ce01",
"name": "Get row(s) in sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
2480,
-16
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/182rAYznmXwoxJQ9cIoRtGDcjocbRaj6_yu6_pFPpCn0/edit#gid=0",
"cachedResultName": "Feuille 1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "182rAYznmXwoxJQ9cIoRtGDcjocbRaj6_yu6_pFPpCn0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/182rAYznmXwoxJQ9cIoRtGDcjocbRaj6_yu6_pFPpCn0/edit?usp=drivesdk",
"cachedResultName": "2025 Nov - workflow n8n dogtreats.com - newsletter subscribers"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "credential-id",
"name": "googleSheetsOAuth2Api Credential"
}
},
"typeVersion": 4.7
},
{
"id": "f215c68b-e806-4689-8153-901b99b22ef9",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
2400,
-208
],
"parameters": {
"color": 4,
"width": 256,
"height": 208,
"content": "## Get Newsletter subscribers\nSheet containing the updated list of all subscribers to this newsletter."
},
"typeVersion": 1
},
{
"id": "d06262e7-896f-478a-b6e9-4b0f3d7651c4",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1952,
-272
],
"parameters": {
"color": 4,
"width": 304,
"height": 272,
"content": "## Load HTML Template\n\nThis node contains the HTML newsletter template for Dog Treats. \nThe template includes placeholders for products which are dynamically injected by this node. \n\nIn this case, the HTML Code was generated using Claude Sonnet 4.5. "
},
"typeVersion": 1
},
{
"id": "4f332fed-93fd-4670-9634-b25fa86ace59",
"name": "Request products from Algolia",
"type": "n8n-nodes-base.httpRequest",
"position": [
-112,
0
],
"parameters": {
"url": "https://Q2OJ96OC70-dsn.algolia.net/1/indexes/dogtreats_prod_products/query",
"method": "POST",
"options": {},
"jsonBody": "{\n \"filters\": \"on_sale:true\",\n \"hitsPerPage\": 6,\n \"attributesToRetrieve\": [\"name\",\"original_price_eur\", \"price_eur\", \"description\", \"image\"]\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpCustomAuth"
},
"credentials": {
"httpCustomAuth": {
"id": "credential-id",
"name": "httpCustomAuth Credential"
}
},
"typeVersion": 4.3
},
{
"id": "05f7d1a1-f2a1-453d-b6fa-8c339960beb6",
"name": "Extract Discounted Products",
"type": "n8n-nodes-base.splitOut",
"position": [
96,
0
],
"parameters": {
"options": {},
"fieldToSplitOut": "hits"
},
"typeVersion": 1
},
{
"id": "5c23ae0c-db7b-4dd3-afde-14a0148cc322",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-208,
-176
],
"parameters": {
"color": 4,
"width": 864,
"height": 144,
"content": "## Gather products currently in promotion from Algolia\n\nGet from Algolia all the products currently in promotion and clean the API response to keep only the product Data needed to populate the newsletter. "
},
"typeVersion": 1
},
{
"id": "38b12246-3725-4055-b6ca-ae8d370b1b76",
"name": "On sundays 8.00 am",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-496,
0
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"triggerAtHour": 8
}
]
}
},
"typeVersion": 1.2
},
{
"id": "bf0a55ac-5c28-4475-9508-4fe4ce82b850",
"name": "What day are we ?",
"type": "n8n-nodes-base.set",
"position": [
-176,
-496
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "61ed8a87-839e-4f1d-80f3-6bed331b6adc",
"name": "Day of week",
"type": "string",
"value": "={{ $json[\"Day of week\"] }}"
},
{
"id": "3253776a-9c2c-4616-8a56-e6823b738381",
"name": "Day of the month",
"type": "string",
"value": "={{ $json[\"Day of month\"] }}"
},
{
"id": "08f2338b-cff4-44c8-b250-75974d826e9f",
"name": "Month",
"type": "string",
"value": "={{ $json.Month }}"
},
{
"id": "0c89c6b5-0fd2-4876-a942-14e8c3a53ffe",
"name": "Year",
"type": "string",
"value": "={{ $json.Year }}"
},
{
"id": "fc9fd0c6-5b87-4e72-a5a4-c02a2d705a73",
"name": "timestamp",
"type": "string",
"value": "={{ $json.timestamp }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "c8121488-e448-4837-ab00-bfc98aa8ba04",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-224,
-944
],
"parameters": {
"color": 4,
"width": 1568,
"height": 656,
"content": "## Determine the valid date range for the promotion (strictly no-code)\n\nThis branch determines the current day of the week and dynamically computes the valid date range that will appear on the newsletter.\nThat range corresponds to the promotional week(from Sunday to Saturday).\n\nNormally, this workflow is scheduled to execute every Sunday, since thatβs when the new promotion week begins.\n\nHowever, the logic here is designed to be slightly smarter: it also supports manual runs during the week.\n\nThis makes it easier for users and testers to run this workflow manually in staging or pre-production\n\nand still generate a realistic week range for the newsletter (without needing to wait until Sunday)."
},
"typeVersion": 1
},
{
"id": "53c14d3e-79c7-4ade-b5b9-7c5990320239",
"name": "Sunday ?",
"type": "n8n-nodes-base.if",
"position": [
0,
-496
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "813258e9-5043-456f-8d60-e6856f6d2b08",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json[\"Day of week\"] }}",
"rightValue": "Sunday"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "d01e06f8-8421-4f04-b1d9-e653cdc37698",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-224,
-1376
],
"parameters": {
"color": 6,
"width": 1568,
"height": 352,
"content": "## \"Low Code\" alternative of the below branch in just one node\n\nUses n8n expressions to outpout the required format in one node, but needs a piece of code to do so. \nIn this very case, it was generated easily with the help of ChatGPT."
},
"typeVersion": 1
},
{
"id": "9470179b-0c7a-4c41-b902-20c436a45810",
"name": "Date range generator (low code)",
"type": "n8n-nodes-base.set",
"position": [
400,
-1216
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "7215ffe4-998a-4640-9920-c1224ab7805b",
"name": "dateRange",
"type": "string",
"value": "={{\n (() => {\n // Base: \"now\" (no upstream node needed)\n const now = new Date();\n\n // Work in UTC to avoid timezone edge cases\n const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n const day = today.getUTCDay(); // 0=Sun ... 6=Sat\n\n const shiftUTC = (base, days) => {\n const d = new Date(base.getTime());\n d.setUTCDate(d.getUTCDate() + days);\n return d;\n };\n\n let start, end;\n if (day === 0) {\n // If today is Sunday (normally the schedule) β upcoming week\n start = today;\n end = shiftUTC(start, 6);\n } else {\n // Otherwise β current week from previous Sunday\n start = shiftUTC(today, -day);\n end = shiftUTC(start, 6);\n }\n\n // Format like \"Nov 9 β Nov 15, 2025\" without locale reliance\n const mon = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];\n const fmt = (d) => `${mon[d.getUTCMonth()]} ${d.getUTCDate()}`;\n const year = start.getUTCFullYear();\n return `${fmt(start)} β ${fmt(end)}, ${year}`;\n })()\n}}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b16c5649-3575-43e5-9c4d-ac6c07d32346",
"name": "Test trigger for low-code branch",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-400,
-1216
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"triggerAtHour": 8
}
]
}
},
"typeVersion": 1.2
},
{
"id": "9ada22f5-f255-4c2c-9c0f-2694b64c6cac",
"name": "Output date of today",
"type": "n8n-nodes-base.set",
"position": [
400,
-640
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "311741bd-1fd6-4275-8c76-21294fff18af",
"name": "timestamp",
"type": "string",
"value": "={{ $json.timestamp }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "a2647e9c-b2d7-4930-8b52-8e523e60be03",
"name": "Calculate end of range",
"type": "n8n-nodes-base.dateTime",
"position": [
800,
-480
],
"parameters": {
"options": {},
"duration": 6,
"magnitude": "={{ $json[\"Previous sunday\"] }}",
"operation": "addToDate"
},
"typeVersion": 2
},
{
"id": "be244160-7466-49a8-8885-fcecc35c8bbd",
"name": "Output Promo Validity Date Range",
"type": "n8n-nodes-base.set",
"position": [
1184,
-480
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "81ef7ab1-9d1a-4c15-ac5c-e9ed142d037a",
"name": "validityRange",
"type": "string",
"value": "={{ $('Clean Promo start date').item.json.formattedDate }} to {{ $json.formattedDate }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "0b0bc1e9-e2df-424d-85c0-58b56bd6b964",
"name": "Find last Monday's date",
"type": "n8n-nodes-base.dateTime",
"position": [
208,
-480
],
"parameters": {
"date": "={{ $json.timestamp }}",
"options": {},
"operation": "roundDate",
"toNearest": "week",
"outputFieldName": "lastMondayDate"
},
"typeVersion": 2
},
{
"id": "4c7cab3f-1db9-4e97-b62d-21543e571cec",
"name": "Find last Sunday's date",
"type": "n8n-nodes-base.dateTime",
"position": [
400,
-480
],
"parameters": {
"options": {},
"duration": 1,
"magnitude": "={{ $json.lastMondayDate }}",
"operation": "subtractFromDate",
"outputFieldName": "Previous sunday"
},
"typeVersion": 2
},
{
"id": "15038e2d-02e2-4f2d-84c5-71f99277f1c1",
"name": "Clean Promo start date",
"type": "n8n-nodes-base.dateTime",
"position": [
608,
-480
],
"parameters": {
"date": "={{ $json[\"Previous sunday\"] }}",
"format": "custom",
"options": {
"includeInputFields": true
},
"operation": "formatDate",
"customFormat": "LLL-d"
},
"typeVersion": 2
},
{
"id": "9aa76aa8-9b88-4260-aa57-a16da58490c6",
"name": "Clean Promo end date",
"type": "n8n-nodes-base.dateTime",
"position": [
992,
-480
],
"parameters": {
"date": "={{ $json.newDate }}",
"format": "custom",
"options": {},
"operation": "formatDate",
"customFormat": "LLL-d-y"
},
"typeVersion": 2
},
{
"id": "0491ec95-0910-44c4-a815-a130416821a5",
"name": "Put back all hits in one clean array",
"type": "n8n-nodes-base.aggregate",
"position": [
528,
0
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData",
"destinationFieldName": "hits"
},
"typeVersion": 1
},
{
"id": "9365da8b-03e1-46b2-b90e-236e373e9fa5",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1072,
272
],
"parameters": {
"width": 624,
"height": 944,
"content": "## Newsletter structure\n\n"
},
"typeVersion": 1
},
{
"id": "888189cb-72ea-4c7a-a247-e1e03eea6e74",
"name": "Send newsletter",
"type": "n8n-nodes-base.gmail",
"position": [
2848,
-16
],
"webhookId": "00b6cc53-4019-45be-9026-abd6e475021f",
"parameters": {
"sendTo": "={{ $('Get row(s) in sheet').item.json.Email }}",
"message": "={{ $('Newsletter Generation (HTML Format)').item.json.html }}",
"options": {
"appendAttribution": false
},
"subject": "=Dogtreats - Promos of the week - {{ $('Output Promo Validity Date Range').item.json.validityRange }}"
},
"credentials": {
"gmailOAuth2": {
"id": "credential-id",
"name": "gmailOAuth2 Credential"
}
},
"typeVersion": 2.1
},
{
"id": "d7fccaa2-8238-4d44-a721-50c9e62e9674",
"name": "Newsletter Generation (HTML Format)",
"type": "n8n-nodes-base.html",
"position": [
2048,
-16
],
"parameters": {
"html": "<!doctype html>\n<html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <meta name=\"x-apple-disable-message-reformatting\">\n <meta name=\"format-detection\" content=\"telephone=no, date=no, address=no, email=no\">\n <title>Dog Treats β Weekly Promotions</title>\n <!--[if mso]>\n <style type=\"text/css\">\n table {border-collapse:collapse;border-spacing:0;border:0;margin:0;}\n div, td {padding:0;}\n div {margin:0 !important;}\n </style>\n <noscript>\n <xml>\n <o:OfficeDocumentSettings>\n <o:PixelsPerInch>96</o:PixelsPerInch>\n </o:OfficeDocumentSettings>\n </xml>\n </noscript>\n <![endif]-->\n <style>\n html, body { margin:0 !important; padding:0 !important; background:#fff8f0 !important; height:100% !important; width:100% !important; }\n body { font-family: Arial, Helvetica, sans-serif !important; color:#3b2e2a !important; }\n * { -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; }\n table { border-spacing:0 !important; border-collapse:collapse !important; mso-table-lspace:0pt !important; mso-table-rspace:0pt !important; }\n table td { border-collapse: collapse; mso-line-height-rule: exactly; }\n img { border:0; height:auto; line-height:100%; outline:none; text-decoration:none; -ms-interpolation-mode: bicubic; }\n a { color:#c2702d !important; text-decoration:none !important; }\n a img { border:none; }\n h1,h2,h3 { color:#4b2d1f !important; margin:0 !important; }\n p { margin: 0 !important; }\n \n /* Prevent Gmail from changing link colors */\n a[x-apple-data-detectors] { color: inherit !important; text-decoration: none !important; }\n \n @media screen and (max-width:900px){\n .container { width:100% !important; max-width:100% !important; }\n .header, .hero, .grid, .footer { padding-left:16px !important; padding-right:16px !important; }\n .mobile-hide { display:none !important; }\n .card-img { height:auto !important; }\n }\n </style>\n </head>\n <body style=\"margin:0; padding:0; background-color:#fff8f0; font-family:Arial, Helvetica, sans-serif; color:#3b2e2a;\">\n <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin:0; padding:0; width:100%; background-color:#fff8f0;\">\n <tr>\n <td align=\"center\" style=\"padding:0;\">\n <table role=\"presentation\" width=\"900\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"width:900px; max-width:900px; margin:24px auto; background-color:#fffaf3; border-radius:12px;\">\n \n <!-- Header -->\n <tr>\n <td style=\"background-color:#f1e0c6; padding:20px 32px; border-bottom:2px solid #e3c18e; color:#4b2d1f;\">\n <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n <tr>\n <td style=\"vertical-align:top;\">\n <div style=\"font-size:22px; font-weight:700; color:#4b2d1f; line-height:28px; margin:0;\">\n <img src=\"https://em-content.zobj.net/source/apple/391/bone_1f9b4.png\" alt=\"π¦΄\" style=\"width:24px; height:24px; display:inline-block; vertical-align:middle; margin-right:4px;\"> Dog Treats\n </div>\n <div style=\"font-size:12px; color:#6e5239; line-height:18px; margin:4px 0 0 0;\">Trusted treats since 2012</div>\n </td>\n <td align=\"right\" style=\"vertical-align:top;\">\n <div style=\"color:#6e5239; font-size:14px; font-weight:bold; line-height:20px;\">Week of {{ $json.dataForNewsletter[0].validityRange }}</div>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- Hero Section - Cleaned Up -->\n <tr>\n <td style=\"padding:24px 32px; background-color:#fffaf3;\">\n <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n <tr>\n <td style=\"padding:0 0 20px 0;\">\n <h1 style=\"margin:0; padding:0; font-size:28px; color:#4b2d1f; line-height:36px; font-weight:700;\">Weekly Promotions</h1>\n </td>\n </tr>\n <tr>\n <td style=\"padding:0;\">\n <p style=\"margin:0; padding:0; font-size:15px; color:#6e5239; line-height:24px;\">All products below are on special promotion this week. Limited stock available.</p>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- Grid 3 columns -->\n <tr>\n <td style=\"padding:16px 32px 24px;\">\n <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n <!-- Row 1 -->\n <tr>\n <!-- Item 0 -->\n <td width=\"33%\" valign=\"top\" style=\"padding:6px;\">\n <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border:1px solid #f0e0c7; border-radius:10px; background-color:#fff; overflow:hidden;\">\n <tr>\n <td>\n <img src=\"{{ $json.dataForNewsletter[1].hits[0].image }}\" alt=\"{{ $json.dataForNewsletter[1].hits[0].name }}\" style=\"width:100%; height:200px; display:block; object-fit:cover;\">\n </td>\n </tr>\n <tr>\n <td style=\"padding:12px;\">\n <div style=\"font-size:14px; font-weight:bold; color:#4b2d1f; margin:0 0 6px 0; line-height:18px;\">{{ $json.dataForNewsletter[1].hits[0].name }}</div>\n <div style=\"font-size:12px; color:#6e5239; margin:0 0 8px 0; line-height:18px; height:36px; overflow:hidden;\">{{ $json.dataForNewsletter[1].hits[0].description }}</div>\n <div style=\"margin:8px 0;\">\n <span style=\"font-weight:bold; font-size:15px; color:#4b2d1f;\">{{ $json.dataForNewsletter[1].hits[0].price_eur }} EUR</span>\n <span style=\"text-decoration:line-through; color:#b28e69; margin-left:8px; font-size:12px;\">{{ $json.dataForNewsletter[1].hits[0].original_price_eur }} EUR</span>\n </div>\n <a href=\"https://www.google.com/search?q=dog+treats\" style=\"display:inline-block; background-color:#d48b39 !important; color:#ffffff !important; padding:8px 14px; border-radius:6px; font-size:13px; font-weight:600; text-decoration:none !important; margin-top:8px;\">View deal</a>\n </td>\n </tr>\n </table>\n </td>\n \n <!-- Item 1 -->\n <td width=\"33%\" valign=\"top\" style=\"padding:6px;\">\n <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border:1px solid #f0e0c7; border-radius:10px; background-color:#fff; overflow:hidden;\">\n <tr>\n <td>\n <img src=\"{{ $json.dataForNewsletter[1].hits[1].image }}\" alt=\"{{ $json.dataForNewsletter[1].hits[1].name }}\" style=\"width:100%; height:200px; display:block; object-fit:cover;\">\n </td>\n </tr>\n <tr>\n <td style=\"padding:12px;\">\n <div style=\"font-size:14px; font-weight:bold; color:#4b2d1f; margin:0 0 6px 0; line-height:18px;\">{{ $json.dataForNewsletter[1].hits[1].name }}</div>\n <div style=\"font-size:12px; color:#6e5239; margin:0 0 8px 0; line-height:18px; height:36px; overflow:hidden;\">{{ $json.dataForNewsletter[1].hits[1].description }}</div>\n <div style=\"margin:8px 0;\">\n <span style=\"font-weight:bold; font-size:15px; color:#4b2d1f;\">{{ $json.dataForNewsletter[1].hits[1].price_eur }} EUR</span>\n <span style=\"text-decoration:line-through; color:#b28e69; margin-left:8px; font-size:12px;\">{{ $json.dataForNewsletter[1].hits[1].original_price_eur }} EUR</span>\n </div>\n <a href=\"https://www.google.com/search?q=dog+treats\" style=\"display:inline-block; background-color:#d48b39 !important; color:#ffffff !important; padding:8px 14px; border-radius:6px; font-size:13px; font-weight:600; text-decoration:none !important; margin-top:8px;\">View deal</a>\n </td>\n </tr>\n </table>\n </td>\n \n <!-- Item 2 -->\n <td width=\"33%\" valign=\"top\" style=\"padding:6px;\">\n <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border:1px solid #f0e0c7; border-radius:10px; background-color:#fff; overflow:hidden;\">\n <tr>\n <td>\n <img src=\"{{ $json.dataForNewsletter[1].hits[2].image }}\" alt=\"{{ $json.dataForNewsletter[1].hits[2].name }}\" style=\"width:100%; height:200px; display:block; object-fit:cover;\">\n </td>\n </tr>\n <tr>\n <td style=\"padding:12px;\">\n <div style=\"font-size:14px; font-weight:bold; color:#4b2d1f; margin:0 0 6px 0; line-height:18px;\">{{ $json.dataForNewsletter[1].hits[2].name }}</div>\n <div style=\"font-size:12px; color:#6e5239; margin:0 0 8px 0; line-height:18px; height:36px; overflow:hidden;\">{{ $json.dataForNewsletter[1].hits[2].description }}</div>\n <div style=\"margin:8px 0;\">\n <span style=\"font-weight:bold; font-size:15px; color:#4b2d1f;\">{{ $json.dataForNewsletter[1].hits[2].price_eur }} EUR</span>\n <span style=\"text-decoration:line-through; color:#b28e69; margin-left:8px; font-size:12px;\">{{ $json.dataForNewsletter[1].hits[2].original_price_eur }} EUR</span>\n </div>\n <a href=\"https://www.google.com/search?q=dog+treats\" style=\"display:inline-block; background-color:#d48b39 !important; color:#ffffff !important; padding:8px 14px; border-radius:6px; font-size:13px; font-weight:600; text-decoration:none !important; margin-top:8px;\">View deal</a>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- Row 2 -->\n <tr>\n <!-- Item 3 -->\n <td width=\"33%\" valign=\"top\" style=\"padding:6px;\">\n <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border:1px solid #f0e0c7; border-radius:10px; background-color:#fff; overflow:hidden;\">\n <tr>\n <td>\n <img src=\"{{ $json.dataForNewsletter[1].hits[3].image }}\" alt=\"{{ $json.dataForNewsletter[1].hits[3].name }}\" style=\"width:100%; height:200px; display:block; object-fit:cover;\">\n </td>\n </tr>\n <tr>\n <td style=\"padding:12px;\">\n <div style=\"font-size:14px; font-weight:bold; color:#4b2d1f; margin:0 0 6px 0; line-height:18px;\">{{ $json.dataForNewsletter[1].hits[3].name }}</div>\n <div style=\"font-size:12px; color:#6e5239; margin:0 0 8px 0; line-height:18px; height:36px; overflow:hidden;\">{{ $json.dataForNewsletter[1].hits[3].description }}</div>\n <div style=\"margin:8px 0;\">\n <span style=\"font-weight:bold; font-size:15px; color:#4b2d1f;\">{{ $json.dataForNewsletter[1].hits[3].price_eur }} EUR</span>\n <span style=\"text-decoration:line-through; color:#b28e69; margin-left:8px; font-size:12px;\">{{ $json.dataForNewsletter[1].hits[3].original_price_eur }} EUR</span>\n </div>\n <a href=\"https://www.google.com/search?q=dog+treats\" style=\"display:inline-block; background-color:#d48b39 !important; color:#ffffff !important; padding:8px 14px; border-radius:6px; font-size:13px; font-weight:600; text-decoration:none !important; margin-top:8px;\">View deal</a>\n </td>\n </tr>\n </table>\n </td>\n \n <!-- Item 4 -->\n <td width=\"33%\" valign=\"top\" style=\"padding:6px;\">\n <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border:1px solid #f0e0c7; border-radius:10px; background-color:#fff; overflow:hidden;\">\n <tr>\n <td>\n <img src=\"{{ $json.dataForNewsletter[1].hits[4].image }}\" alt=\"{{ $json.dataForNewsletter[1].hits[4].name }}\" style=\"width:100%; height:200px; display:block; object-fit:cover;\">\n </td>\n </tr>\n <tr>\n <td style=\"padding:12px;\">\n <div style=\"font-size:14px; font-weight:bold; color:#4b2d1f; margin:0 0 6px 0; line-height:18px;\">{{ $json.dataForNewsletter[1].hits[4].name }}</div>\n <div style=\"font-size:12px; color:#6e5239; margin:0 0 8px 0; line-height:18px; height:36px; overflow:hidden;\">{{ $json.dataForNewsletter[1].hits[4].description }}</div>\n <div style=\"margin:8px 0;\">\n <span style=\"font-weight:bold; font-size:15px; color:#4b2d1f;\">{{ $json.dataForNewsletter[1].hits[4].price_eur }} EUR</span>\n <span style=\"text-decoration:line-through; color:#b28e69; margin-left:8px; font-size:12px;\">{{ $json.dataForNewsletter[1].hits[4].original_price_eur }} EUR</span>\n </div>\n <a href=\"https://www.google.com/search?q=dog+treats\" style=\"display:inline-block; background-color:#d48b39 !important; color:#ffffff !important; padding:8px 14px; border-radius:6px; font-size:13px; font-weight:600; text-decoration:none !important; margin-top:8px;\">View deal</a>\n </td>\n </tr>\n </table>\n </td>\n \n <!-- Item 5 -->\n <td width=\"33%\" valign=\"top\" style=\"padding:6px;\">\n <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"border:1px solid #f0e0c7; border-radius:10px; background-color:#fff; overflow:hidden;\">\n <tr>\n <td>\n <img src=\"{{ $json.dataForNewsletter[1].hits[5].image }}\" alt=\"{{ $json.dataForNewsletter[1].hits[5].name }}\" style=\"width:100%; height:200px; display:block; object-fit:cover;\">\n </td>\n </tr>\n <tr>\n <td style=\"padding:12px;\">\n <div style=\"font-size:14px; font-weight:bold; color:#4b2d1f; margin:0 0 6px 0; line-height:18px;\">{{ $json.dataForNewsletter[1].hits[5].name }}</div>\n <div style=\"font-size:12px; color:#6e5239; margin:0 0 8px 0; line-height:18px; height:36px; overflow:hidden;\">{{ $json.dataForNewsletter[1].hits[5].description }}</div>\n <div style=\"margin:8px 0;\">\n <span style=\"font-weight:bold; font-size:15px; color:#4b2d1f;\">{{ $json.dataForNewsletter[1].hits[5].price_eur }} EUR</span>\n <span style=\"text-decoration:line-through; color:#b28e69; margin-left:8px; font-size:12px;\">{{ $json.dataForNewsletter[1].hits[5].original_price_eur }} EUR</span>\n </div>\n <a href=\"https://www.google.com/search?q=dog+treats\" style=\"display:inline-block; background-color:#d48b39 !important; color:#ffffff !important; padding:8px 14px; border-radius:6px; font-size:13px; font-weight:600; text-decoration:none !important; margin-top:8px;\">View deal</a>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n\n <!-- Footer -->\n <tr>\n <td style=\"padding:24px 32px; background-color:#fff3e0; font-size:12px; color:#7a5b42; text-align:center; border-top:1px solid #f0e0c7;\">\n <div style=\"margin:0 0 16px 0; line-height:18px;\">\n Dog Treats - 123 Bone Street, Paris 75000<br>\n <a href=\"mailto:user@example.com\" style=\"color:#7a5b42; text-decoration:underline;\">user@example.com</a>\n </div>\n \n <!-- Social Icons with PNG images -->\n <table role=\"presentation\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"margin:16px auto;\">\n <tr>\n <td style=\"padding:0 8px;\">\n <a href=\"https://instagram.com/dogtreats\" title=\"Instagram\" style=\"display:inline-block;\">\n <img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Instagram_logo_2016.svg/132px-Instagram_logo_2016.svg.png\" alt=\"Instagram\" style=\"width:40px; height:40px; display:block; border:0;\">\n </a>\n </td>\n <td style=\"padding:0 8px;\">\n <a href=\"https://facebook.com/dogtreats\" title=\"Facebook\" style=\"display:inline-block;\">\n <img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/b/b9/2023_Facebook_icon.svg/100px-2023_Facebook_icon.svg.png\" alt=\"Facebook\" style=\"width:40px; height:40px; display:block; border:0;\">\n </a>\n </td>\n <td style=\"padding:0 8px;\">\n <a href=\"https://tiktok.com/@dogtreats\" title=\"TikTok\" style=\"display:inline-block;\">\n <img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Ionicons_logo-tiktok.svg/512px-Ionicons_logo-tiktok.svg.png\" alt=\"TikTok\" style=\"width:40px; height:40px; display:block; border:0;\">\n </a>\n </td>\n </tr>\n </table>\n \n <p style=\"margin:16px 0 0 0; line-height:18px;\"><a href=\"https://tiktok.com/@dogtreats\" style=\"color:#7a5b42; text-decoration:underline;\">Follow us on TikTok</a></p>\n \n <div style=\"margin:12px 0 0 0; font-size:11px; line-height:16px;\">\n <p style=\"margin:0; line-height:16px;\">You're receiving this because you subscribed to Weekly Promotions.<br>\n <a href=\"https://dogtreats.example/preferences\" style=\"color:#6e5b42; text-decoration:underline;\">Manage preferences</a> - <a href=\"https://dogtreats.example/unsubscribe\" style=\"color:#6e5b42; text-decoration:underline;\">Unsubscribe</a></p>\n </div>\n </td>\n </tr>\n\n </table>\n </td>\n </tr>\n </table>\n </body>\n</html>"
},
"typeVersion": 1.2
},
{
"id": "2a69aa11-d8d8-4a1d-81c8-28d5364e775c",
"name": "Merge data for newsletter",
"type": "n8n-nodes-base.merge",
"position": [
1440,
-16
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "11c48185-b60a-43b1-be2b-341c54fbb1da",
"name": "Aggregate data for Newsletter",
"type": "n8n-nodes-base.aggregate",
"position": [
1728,
-16
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData",
"destinationFieldName": "dataForNewsletter"
},
"typeVersion": 1
},
{
"id": "29c0a766-9582-4bb1-9851-10626218ff26",
"name": "Keep only useful product data",
"type": "n8n-nodes-base.set",
"position": [
304,
0
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f8d48366-a7f1-4f86-815d-0bae70594832",
"name": "name",
"type": "string",
"value": "={{ $json.name }}"
},
{
"id": "8bc85a37-a248-4250-9d70-f619a6823a08",
"name": "price_eur",
"type": "string",
"value": "={{ $json.price_eur }}"
},
{
"id": "9ef3edc3-cca6-4018-a2e1-dabba5ae91ca",
"name": "description",
"type": "string",
"value": "={{ $json.description }}"
},
{
"id": "a1071970-c266-4327-812d-ad21e3470842",
"name": "objectID",
"type": "string",
"value": "={{ $json.objectID }}"
},
{
"id": "866cbd89-5b47-4093-8dfe-ab74afbcae54",
"name": "image",
"type": "string",
"value": "={{ $json.image }}"
},
{
"id": "4996a32d-3a3b-4e34-b5a4-cb7e98f57a44",
"name": "original_price_eur",
"type": "number",
"value": "={{ $json.original_price_eur }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "1b01a692-31cf-4903-bf7e-fcf45358b3f2",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
1824,
272
],
"parameters": {
"width": 624,
"height": 944,
"content": "## Newsletter prepared\n\n"
},
"typeVersion": 1
},
{
"id": "bea4b20e-885c-4f0d-a5e0-68294ad346ac",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1200,
80
],
"parameters": {
"color": 6,
"width": 198,
"height": 80,
"content": "### Product tiles (Thumbnails + Infos)"
},
"typeVersion": 1
},
{
"id": "93b83118-a005-4140-bdbd-33e36d48342e",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
1152,
-176
],
"parameters": {
"color": 6,
"width": 192,
"height": 80,
"content": "### Promo Validity Date (date range)"
},
"typeVersion": 1
},
{
"id": "842d183f-d094-4cd7-9dad-ce8bcc6cf0b0",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1376,
-1312
],
"parameters": {
"width": 624,
"height": 1328,
"content": "## Automated Weekly Newsletter for E-commerce Promotions (based on Algolia)\n\nThis workflow automatically sends a beautifully designed HTML newsletter every Sunday at 8 AM, featuring products currently on sale from your Algolia-powered e-commerce store.\n\n## Who's it for\n\nPerfect for e-commerce store owners, marketing teams, and anyone running promotional campaigns who wants to automate their weekly newsletter without relying on expensive email marketing platforms.\n\n## How it works\n\n1. **Triggers every Sunday at 8:00 AM** - Scheduled to start each new promotion week\n2. **Fetches discounted products** - Queries your Algolia index for 6 products marked with `on_sale:true`\n3. **Calculates promotion dates** - Automatically generates the week's date range (Sunday to Saturday)\n4. **Builds HTML newsletter** - Populates a responsive email template with product images, prices, and descriptions\n5. **Retrieves subscribers** - Pulls the latest subscriber list from your Google Sheets\n6. **Sends personalized emails** - Delivers the newsletter to all subscribers via Gmail\n\n## Set up steps\n\n**Setup time: ~15 minutes**\n\n1. Connect your **Algolia credentials** (Search API key + Application ID)\n2. Update the **Algolia index name** to match your store (currently set to `dogtreats_prod_products`)\n3. Create a **Google Sheet** with subscriber emails (column named \"Email\")\n4. Connect your **Google Sheets** and **Gmail** accounts\n5. (Optional) Customize the HTML template colors and branding to match your store\n\n## Requirements\n\n- Algolia account with a product index containing `on_sale`, `price_eur`, `original_price_eur`, `image`, `name`, and `description` fields\n- Google Sheets with subscriber list\n- Gmail account for sending emails\n\n## How to customize\n\n- **Change promotion criteria**: Modify the filter in \"Request products from Algolia\" node (e.g., `category:shoes` instead of `on_sale:true`)\n- **Adjust product count**: Change `hitsPerPage` value (currently 6)\n- **Modify schedule**: Update the trigger node to run on different days/times\n- **Personalize email design**: Edit the HTML template node to match your brand colors and style\n- **Add unsubscribe logic**: Extend the workflow to handle unsubscribe requests\n\nπ‘ **Pro tip**: Use the manual execution button to test the workflow mid-week - it's \"smart\" enough to calculate the current promotion week even when not running on Sunday."
},
"typeVersion": 1
},
{
"id": "60c88e0e-ed1b-432d-ab67-3b1be3734d4d",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
3120,
-48
],
"parameters": {
"width": 320,
"height": 144,
"content": "## Questions or Feedback?\n\nπ§ emir.belkahia@gmail.com \nπΌ [linkedin.com/in/emirbelkahia](https://www.linkedin.com/in/emirbelkahia/)"
},
"typeVersion": 1
},
{
"parameters": {
"operation": "verify",
"email": "={{ $('Get row(s) in sheet').item.json.Email }}",
"additionalOptions": {}
},
"type": "n8n-nodes-billionverify.billionVerify",
"typeVersion": 1,
"position": [
2488,
-16
],
"name": "Verify Email (BillionVerify)",
"credentials": {
"billionVerifyApi": {
"id": "",
"name": "BillionVerify account"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "is-deliverable",
"leftValue": "={{ $json.is_deliverable }}",
"rightValue": "",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
]
}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
2668,
-16
],
"name": "IF deliverable"
}
],
"connections": {
"Sunday ?": {
"main": [
[
{
"node": "Output date of today",
"type": "main",
"index": 0
}
],
[
{
"node": "Find last Monday's date",
"type": "main",
"index": 0
}
]
]
},
"What day are we ?": {
"main": [
[
{
"node": "Sunday ?",
"type": "main",
"index": 0
}
]
]
},
"On sundays 8.00 am": {
"main": [
[
{
"node": "Request products from Algolia",
"type": "main",
"index": 0
},
{
"node": "What day are we ?",
"type": "main",
"index": 0
}
]
]
},
"Get row(s) in sheet": {
"main": [
[
{
"node": "Verify Email (BillionVerify)",
"type": "main",
"index": 0
}
]
]
},
"Clean Promo end date": {
"main": [
[
{
"node": "Output Promo Validity Date Range",
"type": "main",
"index": 0
}
]
]
},
"Output date of today": {
"main": [
[
{
"node": "Clean Promo start date",
"type": "main",
"index": 0
}
]
]
},
"Calculate end of range": {
"main": [
[
{
"node": "Clean Promo end date",
"type": "main",
"index": 0
}
]
]
},
"Clean Promo start date": {
"main": [
[
{
"node": "Calculate end of range",
"type": "main",
"index": 0
}
]
]
},
"Find last Monday's date": {
"main": [
[
{
"node": "Find last Sunday's date",
"type": "main",
"index": 0
}
]
]
},
"Find last Sunday's date": {
"main": [
[
{
"node": "Clean Promo start date",
"type": "main",
"index": 0
}
]
]
},
"Merge data for newsletter": {
"main": [
[
{
"node": "Aggregate data for Newsletter",
"type": "main",
"index": 0
}
]
]
},
"Extract Discounted Products": {
"main": [
[
{
"node": "Keep only useful product data",
"type": "main",
"index": 0
}
]
]
},
"Aggregate data for Newsletter": {
"main": [
[
{
"node": "Newsletter Generation (HTML Format)",
"type": "main",
"index": 0
}
]
]
},
"Keep only useful product data": {
"main": [
[
{
"node": "Put back all hits in one clean array",
"type": "main",
"index": 0
}
]
]
},
"Request products from Algolia": {
"main": [
[
{
"node": "Extract Discounted Products",
"type": "main",
"index": 0
}
]
]
},
"Output Promo Validity Date Range": {
"main": [
[
{
"node": "Merge data for newsletter",
"type": "main",
"index": 0
}
]
]
},
"Test trigger for low-code branch": {
"main": [
[
{
"node": "Date range generator (low code)",
"type": "main",
"index": 0
}
]
]
},
"Newsletter Generation (HTML Format)": {
"main": [
[
{
"node": "Get row(s) in sheet",
"type": "main",
"index": 0
}
]
]
},
"Put back all hits in one clean array": {
"main": [
[
{
"node": "Merge data for newsletter",
"type": "main",
"index": 1
}
]
]
},
"Verify Email (BillionVerify)": {
"main": [
[
{
"node": "IF deliverable",
"type": "main",
"index": 0
}
]
]
},
"IF deliverable": {
"main": [
[
{
"node": "Send newsletter",
"type": "main",
"index": 0
}
],
[]
]
}
},
"settings": {
"executionOrder": "v1"
}
}Workflow templates with Algolia
Ready-to-use workflows that verify emails before Algolia sends.
How it works
- 1
Integrate BillionVerify via the n8n community node, Integrately, or a direct REST API call in your data pipeline.
- 2
Before writing or updating a record in Algolia, pass its email field to BillionVerify.
- 3
Receive a structured result: valid, invalid, disposable, role-based, or catch-all.
- 4
Proceed with indexing only for addresses that pass verification; flag or reject the rest.
- 5
Use the verification metadata as an additional attribute in the Algolia record for filtering and search rules.
When to use this
Clean user email data before indexing
Before writing a new user record to Algolia, verify the email address with BillionVerify. Invalid and disposable addresses are caught immediately, preventing low-quality data from ever entering your search index.
Audit existing indexed records
Export email fields from your Algolia index and run a bulk verification pass. Update or remove records with undeliverable addresses to improve the integrity of your user data across dependent systems.
FAQ
Can BillionVerify results be stored as attributes in Algolia records?
Yes. You can store the verification verdict and timestamp as custom attributes on each Algolia record, enabling you to filter search results or trigger re-verification workflows based on data age.
How does verifying emails improve Algolia-powered personalization?
Personalization relies on accurate user identity. Invalid emails create duplicate or ghost profiles that skew recommendation models and dilute behavioral data, so clean email fields lead to better personalization outcomes.
Is bulk verification supported for large Algolia indices?
BillionVerify's bulk API accepts large batches in a single request, making it practical to audit thousands of indexed email addresses in one pass without rate-limit concerns.
Does BillionVerify integrate directly with Algolia?
There is no native direct connector, but you can wire them together using n8n, Integrately, or a custom script that reads from Algolia, verifies with BillionVerify, and writes results back.
Verify emails in Algolia
Create a free account, grab your API key, and stop bounces before they happen.
Get started free