Skip to main content

n8n Workflow: Alerting Your Team When a Returning Visitor Comes Back to Your Website

Updated over a week ago

Overview

This guide shows you how to build an n8n workflow that notifies your team in Slack whenever a previously-identified visitor returns to your website.

In this example, we use Slack to send alerts.


Feel free to use any tools your tech stack supports — HubSpot, Salesforce, Teams, email, etc. The logic stays the same.

This workflow is ideal for:

  • Account-based outreach

  • High-intent visitor alerts

  • Notifying sales when warm visitors come back

  • Re-engagement monitoring

  • Lead scoring based on multi-day activity

It builds on your primary RB2B visitor-tracking workflow and branches directly from your existing Build Returning Visitor Row node.

What This Workflow Does

Each time RB2B identifies a visitor:

  1. This returning-visitor branch then checks whether the visitor has come back on a different day than before.

  2. If so, the workflow:

    • builds a Slack message

    • sends an alert to your chosen Slack channel

  3. If not, the workflow ends quietly with no alert.

This gives your team real-time visibility into meaningful repeat engagement.

Step-By-Step Workflow

Below is every node involved in this returning-visitor alert branch, in order.

1. IF Node: Check if Returning Over Multiple Days

Branching off the Build Returning Visitor Row node, this node checks if the visitor has returned on a different calendar day than their previous visit.

Condition 1: {{ $json.unique_days_count }} is greater than 1

Condition 2: {{ $json.company_name }} is not empty

This means:

  • If the visitor has been seen on more than one unique day, the workflow continues to the Slack alert.

  • If the visitor’s visits happened only on a single day, the workflow ends with no alert.

  • The second condition is a quick check to make sure that we've captured a company name for the visitor as well.

This prevents noise from same-day page views and focuses on meaningful return activity.

2. Code Node: Build Returning Visitor Slack Block (Code)

This node builds a message like:

‼️ RETURN VISITOR DETECTED ‼️
John Doe from RB2B
Head of Example Code
Email: [email protected]
LinkedIn: http://www.linkedin.com/company/rb2b

Total page views: 7
Unique days visited: 4

Visit history by day:
• 2025-11-19
- https://www.rb2b.com/apis
• 2025-11-18
- https://www.rb2b.com/apis
- https://www.rb2b.com/pricing
- https://www.rb2b.com/apis

The node outputs a single value:

slack_text

Code:

const person = $json;

// Basic identity info
const firstName = person.first_name || "Anonymous";
const lastName = person.last_name || "Visitor";
const fullName = `${firstName} ${lastName}`.trim();

const company = person.company_name || "Unknown company";
const email = person.business_email || "no email";
const website = person.website || "";
const title = person.title || "";
const linkedin = person.identity_key || "";

const pageViews = person.page_views || 0;

// Parse all_pages array
let allPages = [];
try {
allPages = JSON.parse(person.all_pages || "[]");
} catch (e) {
allPages = [];
}

// Group pages by date (YYYY-MM-DD)
const daysMap = {};
for (const p of allPages) {
if (!p.seen_at) continue;
const day = p.seen_at.slice(0, 10); // "YYYY-MM-DD"
const url = p.url || "(unknown URL)";

if (!daysMap[day]) daysMap[day] = [];
daysMap[day].push(url);
}

// Sort days (latest first)
const days = Object.keys(daysMap).sort().reverse();
const uniqueDaysCount = days.length;

// Build Slack message lines
const lines = [];

lines.push(`‼️ *RETURN VISITOR DETECTED* ‼️`);
lines.push(`*${fullName}* from *${company}*`);
if (title) lines.push(`${title}`);
lines.push(`*Email:* ${email}`);
lines.push(`*LinkedIn:* ${linkedin}`);
lines.push(""); // blank line
lines.push(`*Total page views:* ${pageViews}`);
lines.push(`*Unique days visited:* ${uniqueDaysCount}`);
lines.push(""); // blank line

// List the days
if (days.length > 0) {
lines.push(`*Visit history by day:*`);

for (const day of days) {
lines.push(`• *${day}*`);
const urls = daysMap[day];

urls.forEach((url) => {
lines.push(` - ${url}`);
});
}
} else {
lines.push(`_No page history available_`);
}

const slack_text = lines.join("\n");

return [
{
slack_text
}
];

3. Slack Node: Send Slack Message About Returning Visitor

  • Message Type: Simple Text Message

  • Message Text: ={{ $json.slack_text }}

  • Channel: your chosen alert channel (e.g., rb2b_n8n_alerts)

  • Use Markdown: Off (simple Slack bold/italics still work)

This sends an immediate alert to your team whenever a visitor returns to your site on a new day.

Optional: Add a "time between visits" threshold

You may only want alerts when someone comes back after a meaningful gap, for example more than 7 days between their first visit and their latest visit.

You can add that as a second condition to Check if returning over multiple days.

Updated IF logic

Edit your Check if returning over multiple days node and use an expression that combines both checks:

{{
$json.unique_days_count > 1 &&
(
(new Date($json.last_seen) - new Date($json.first_seen)) /
(1000 * 60 * 60 * 24)
) > 7
}}

Operator: is true

This expression does two things:

  1. unique_days_count > 1

    • Confirms the visitor has been on your site across more than one unique calendar day.

  2. (new Date(last_seen) - new Date(first_seen)) / (1000 * 60 * 60 * 24) > 7

    • Calculates the number of days between the first and latest visit.

    • Only passes if the difference is greater than 7 days.

You can change 7 to any threshold that makes sense for your team, for example 1 for at least one day apart, 30 for long term return visitors, and so on.

With this in place, Slack alerts are sent only when:

  • The visitor has visited on more than one unique day, and

  • At least 7 days have passed between their first visit and their most recent visit.

Did this answer your question?