LinkedIn to Google Sheets, DMs logged automatically
You get profile views on LinkedIn, and you know they matter. Then the tab closes, the day gets busy, and those “warm” visitors quietly turn into missed conversations and lost deals.
Sales reps feel it first, honestly. But recruiters chasing passive candidates and founders doing partnerships run into the same wall: LinkedIn DM logging becomes a messy, manual habit you never quite keep up with.
This n8n workflow pulls your recent profile visitors, sends the right kind of outreach (DM or connection request), and logs everything to Google Sheets so you always know who you contacted and what happened next.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: LinkedIn to Google Sheets, DMs logged automatically
flowchart LR
subgraph sg0["Weekly Schedule Flow"]
direction LR
n0["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Extract Profile ID from URL"]
n1["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Fetch Profile Visitors"]
n2@{ icon: "mdi:play-circle", form: "rounded", label: "Weekly Schedule Trigger", pos: "b", h: 48 }
n3["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Send Connection Request"]
n4@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check if 1st Degree Connection", pos: "b", h: 48 }
n5["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Send DM to Connected User"]
n6["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Generate Message for New Con.."]
n7["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Generate DM for Connected User"]
n8@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Visitors Array", pos: "b", h: 48 }
n9@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items", pos: "b", h: 48 }
n10@{ icon: "mdi:cog", form: "rounded", label: "Continue to Next Visitor", pos: "b", h: 48 }
n11@{ icon: "mdi:cog", form: "rounded", label: "Wait Between Messages", pos: "b", h: 48 }
n12@{ icon: "mdi:database", form: "rounded", label: "Log DM Sent to Sheet", pos: "b", h: 48 }
n13@{ icon: "mdi:database", form: "rounded", label: "Check if Already Contacted", pos: "b", h: 48 }
n14@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Skip if Already Contacted", pos: "b", h: 48 }
n15@{ icon: "mdi:database", form: "rounded", label: "Log Connection Request to Sh..", pos: "b", h: 48 }
n9 --> n13
n12 --> n10
n8 --> n9
n11 --> n9
n1 --> n8
n3 --> n15
n2 --> n1
n10 --> n11
n5 --> n12
n14 --> n0
n14 --> n11
n13 --> n14
n0 --> n4
n4 --> n7
n4 --> n6
n7 --> n5
n15 --> n10
n6 --> n3
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n2 trigger
class n4,n14 decision
class n12,n13,n15 database
class n1,n3,n5 api
class n0,n6,n7 code
classDef customIcon fill:none,stroke:none
class n0,n1,n3,n5,n6,n7 customIcon
The Problem: Profile visitors slip through the cracks
LinkedIn profile visitors are a rare signal because they already did the hardest part: they showed interest. The frustrating part is how easy it is to waste that signal. You have to remember to check the visitors list, decide if you’re connected, write something that doesn’t sound copy-pasted, then track it somewhere so you don’t message the same person again next week. Miss a few days and it snowballs. Suddenly you’re either spamming by accident, or you’re doing nothing and hoping “they’ll reach out.”
None of these steps is awful on its own. Together, they create constant drag.
- Checking visitors and triaging them can take about 30 minutes every week, and it’s never on your calendar when you need it.
- People get contacted twice because the “I already messaged them” note lives in someone’s memory, not in a system.
- First-degree connections and 2nd/3rd-degree visitors need different outreach, but manual sorting leads to the wrong message type going out.
- Follow-up falls apart because there’s no clean log of who was contacted, when it happened, and what the status is.
The Solution: Auto-message visitors and track outreach in Sheets
This workflow runs on a schedule (weekly by default, but you can make it daily) and pulls your LinkedIn profile visitors from the last 7 days using the ConnectSafely.ai API. It then processes visitors one at a time, checks Google Sheets to see if they’ve already been contacted, and skips anyone who’s already in your log. For new visitors, it looks at the connection degree to decide what to send. If you’re already connected, it sends a personalized DM. If you’re not connected yet, it sends a connection request with a short message. After each outreach, it writes a row to Google Sheets so you have a reliable record for follow-up.
The workflow starts with a scheduled run, fetches and splits the visitor list, then deduplicates against your sheet before messaging. It finishes by waiting between sends to keep activity patterns looking human, then loops until the visitor batch is done.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you average 40 profile visitors a week. Manually, you might spend about 2 minutes opening each profile, another 3 minutes writing the right message, plus a minute to log it somewhere, which is roughly 4 hours total. With this workflow, you set up the message templates once, then a weekly run fetches the last 7 days of visitors, sends the right DM or connection note, and logs it automatically. Your “work” becomes reviewing the Google Sheet for replies and next steps, which is closer to 15 minutes.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- ConnectSafely.ai for LinkedIn visitors + messaging API
- Google Sheets to store outreach logs and statuses
- ConnectSafely.ai API key (Settings → API Keys in dashboard)
Skill level: Intermediate. You’ll connect credentials, paste an API key, and edit two short message-template code blocks.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
A weekly (or daily) schedule kicks it off. n8n starts the run automatically, or you can trigger it manually when you want to process visitors right now.
Visitor data is pulled and split into single records. The workflow calls the ConnectSafely.ai API for “past_7_days,” then breaks the response into individual visitors so each person is handled cleanly.
Deduplication happens before any message is sent. n8n looks up each visitor in Google Sheets (using the LinkedIn URL) and skips outreach if the person already exists in your tracking sheet. Simple. Effective.
The workflow sends a DM or a connection request. It checks the visitor’s connection degree, generates a message from your templates, then sends either a direct message (for 1st-degree connections) or a connection invite note (for 2nd/3rd-degree visitors).
Everything is logged, then pacing keeps you safe. After each send, it writes a row to Google Sheets with name, LinkedIn URL, and status. A short wait between messages helps maintain natural activity patterns, then the loop continues.
You can easily modify the visitor time window to cover the past 30 days, or change the message templates to match your offer and tone based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Schedule Trigger
Set the weekly schedule that starts the outreach flow.
- Add Weekly Automation Trigger and set the rule interval to weeks.
- Connect Weekly Automation Trigger to Retrieve Profile Visitors to start the workflow.
Step 2: Connect Google Sheets
Configure your tracking sheet so the workflow can look up and log outreach attempts.
- Open Lookup Prior Contact and set Document to
[YOUR_ID]and Sheet toSheet1(gid=0). - Set the filter in Lookup Prior Contact to look up Linkedin URL with
{{ $json.navigationUrl }}. - Open Record DM in Sheet and set Operation to
appendOrUpdatewith columns mapping: Name →{{ $('Iterate Visitor Batch').item.json.name }}, Linkedin URL →{{ $('Iterate Visitor Batch').item.json.navigationUrl }}, Status →DONE. - Open Record Invite in Sheet and mirror the same Operation and column mapping as Record DM in Sheet.
- Credential Required: Connect your Google Sheets credentials in Lookup Prior Contact, Record DM in Sheet, and Record Invite in Sheet.
Step 3: Set Up Visitor Retrieval and Looping
Fetch LinkedIn visitors, split them into items, and loop with a delay to avoid rate limits.
- Configure Retrieve Profile Visitors with URL
https://api.connectsafely.ai/linkedin/profile/visitors, MethodPOST, and JSON Body{"timeRange":"past_7_days","start":0,"fetchAll":true}. - Set Authentication to
genericCredentialTypeand Generic Auth Type tohttpBearerAuthin Retrieve Profile Visitors. - Configure Split Visitor List with Field to Split Out set to
visitors. - Ensure the loop order is Split Visitor List → Iterate Visitor Batch → Lookup Prior Contact, and that Advance Visitor Loop → Pause Between Outreach → Iterate Visitor Batch completes the cycle.
- Credential Required: Connect your HTTP Bearer Auth credentials in Retrieve Profile Visitors.
Step 4: Set Up Processing and Routing Logic
Parse the profile identifier, decide whether to message or connect, and compose outreach messages.
- Configure Branch on Contact Status to use the condition
{{ $json.isEmpty() }}with the operator set to boolean false. - In Parse Profile Identifier, keep the provided JavaScript to extract
profile_idfromnavigationUrl. - Set Evaluate Connection Level to check
{{ $('Iterate Visitor Batch').item.json.connectionDegree }}equals1st. - Customize message templates inside Compose Connected DM and Draft Connection Note by replacing placeholders like
[YOUR PRODUCT]and[VALUE PROP].
/in/ in the URL, profile_id will be null and message sending will fail.Step 5: Configure Output Action Nodes
Send a direct message to 1st-degree connections or a connection invite to others, then record each action.
- In Dispatch Direct Message, set URL to
https://api.connectsafely.ai/linkedin/messageand Method toPOST. - Set Body Parameters in Dispatch Direct Message to recipientProfileId
{{ $('Parse Profile Identifier').item.json.profile_id }}, message{{ $json.message }}, and messageTypeinmail. - In Send Connection Invite, set URL to
https://api.connectsafely.ai/linkedin/connectand profileId to{{ $('Parse Profile Identifier').item.json.profile_id }}. - Confirm the success path: Compose Connected DM → Dispatch Direct Message → Record DM in Sheet, and the non-connected path: Draft Connection Note → Send Connection Invite → Record Invite in Sheet.
- Credential Required: Connect your HTTP Bearer Auth credentials in Dispatch Direct Message and Send Connection Invite.
Step 6: Test & Activate Your Workflow
Run a manual test and verify that messages and sheet updates are working as expected.
- Click Execute Workflow to run a manual test starting at Weekly Automation Trigger.
- Verify that Retrieve Profile Visitors returns a
visitorsarray and that Split Visitor List produces individual visitor items. - Confirm that either Dispatch Direct Message or Send Connection Invite runs based on Evaluate Connection Level.
- Check that Record DM in Sheet or Record Invite in Sheet writes a row with Status
DONE. - Turn on the workflow using the Active toggle to enable weekly automation.
Common Gotchas
- ConnectSafely.ai credentials can expire or lack permissions. If things break, check your API key in the ConnectSafely.ai dashboard (Settings → API Keys) first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Frequently Asked Questions
About an hour if your accounts are ready.
No, not really. You will edit two message templates, but it’s copy/paste-level and easy to test.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in ConnectSafely.ai subscription costs (free trial, then paid) since it provides the LinkedIn API access.
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes. Add an IF check right after the visitor data is parsed, then route non-matching visitors straight to the wait/loop so they never get messaged. Common filters include job title keywords, company name matches, and excluding existing customers by keeping a “do not contact” list in your Google Sheet.
Usually it’s an expired or incorrect API key, so regenerate it in the ConnectSafely.ai dashboard and update the HTTP Bearer Auth credential in n8n. Also confirm your LinkedIn account is connected inside ConnectSafely.ai, because the API returns empty results if that link is broken. If the workflow started failing after working fine, check the HTTP Request node responses for rate limit or authorization errors.
Plenty for most small teams: dozens per day is realistic if you keep conservative waits, and the workflow loops through each visitor one-by-one. On n8n Cloud, the practical limit is your monthly executions on your plan; if you self-host, you’re mostly limited by your server and how aggressive you set the schedule. LinkedIn safety matters more than raw throughput here, so start around 10–15 messages a day and scale slowly.
Often, yes, because the logic here isn’t just a straight line. You’re looping through visitors, branching by connection degree, deduplicating against a sheet, and pacing requests so your account doesn’t get flagged. n8n handles that kind of multi-step flow without turning it into a fragile mess of separate zaps. Zapier or Make can still work if you’re doing very low volume and you don’t need batching or more advanced conditions. If you want a second opinion before you commit, Talk to an automation expert.
Once this is running, profile views stop being “nice to see” and start becoming a steady outreach queue you can actually follow through on. Set it up, keep the messages human, and let the sheet do the remembering.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.