Automate your job search and reach the hiring contact with n8n

Search LinkedIn, RemoteOK, and We Work Remotely daily, score every job with AI, draft an application note, find the recruiter or hiring manager on LinkedIn, and send them a connection request.

Run a daily job search across LinkedIn, RemoteOK, and We Work Remotely, score every opening against your profile with AI, draft an application note for strong fits, find the right person at each company on LinkedIn, and send them a personalized connection request under your name. Every job lands in Google Sheets with its score, notes, and outreach status.

Why being early matters in a job search, and how to run the same flow from MCP or REST: see the playbook Automate your LinkedIn job search.

Import the template: Search and outreach to top-fit jobs with LinkedIn, RemoteOK, WWR, Claude and Sheets

What you need

  • A Periodix Actions account with a connected LinkedIn profile (3-day free trial)
  • The Periodix Actions node installed (listed in n8n as Periodix LinkedIn), see Installation
  • An AI provider API key: Claude by default, OpenAI or Gemini also work
  • A Google Sheet with a Leads tab and these column headers: source, job_title, company_name, company_id, company_match, job_url, job_location, fit_score, work_mode, fit_reason, application_note, recipient_name, recipient_headline, recipient_id, recipient_match, connection_note, connection_sent

Workflow at a glance

Run Daily → Search Config → Search LinkedIn Jobs (Periodix Actions) + Fetch RemoteOK + Fetch We Work Remotely → Normalize each source → Merge → Deduplicate → Resolve LinkedIn company (Periodix Actions) → Score Fit with AI → Keep Strong Fits → Draft Application with AI → Find Recipient at Company (Periodix Actions) → Draft Connection Note → Send Connection Request (Periodix Actions) → Save Leads

Step by step

1. Run Daily (Schedule Trigger)

Runs once a day at 8:00. Good roles collect applicants fast, so a daily run keeps you early.

2. Search Config (Set node)

FieldExampleWhat it controls
job_keywordsGrowth Manager OR Marketing Operations Manager OR GTM ManagerLinkedIn Jobs search keywords
linkedin_geo_id105015875LinkedIn location ID (105015875 is France)
freshness_hours48Only jobs posted in the last N hours
jobs_limit25Max LinkedIn jobs per run
keyword_listgrowth, marketing operations, gtm, revenue operationsFilter for RemoteOK and We Work Remotely titles and tags
wwr_feed_url
We Work Remotely RSS feed
candidate_profileYour role, years of experience, one or two resultsPassed to AI for scoring and drafting
candidate_preferencesWanted roles, roles to avoid, location, remote or hybrid, minimum payPassed to AI for scoring
candidate_nameYour NameUsed in application and connection notes
recipient_titlesRecruiter, Talent Acquisition, Technical Recruiter, Hiring ManagerWho to reach at each company

To find a linkedin_geo_id, run a job search on LinkedIn with your location and copy the geoId value from the URL.

3. Search LinkedIn Jobs (Periodix Actions: Search)

  • Resource: Search
  • Profile: your connected LinkedIn profile
  • Search URL:
  • Limit: {{ $('Search Config').first().json.jobs_limit }}
f_TPR=r plus a number of seconds is LinkedIn's "posted within" filter. LinkedIn jobs already include the company ID.

4. Fetch RemoteOK and Fetch We Work Remotely (HTTP Request + RSS Read)

Run in parallel with the LinkedIn search. RemoteOK is read from its public API, We Work Remotely from its RSS feed. Both use On Error: Continue, so one board being down does not stop the run.

5. Normalize, Merge, and Deduplicate (Code + Merge nodes)

All three sources are mapped to the same fields: source, job_title, company_name, company_id, job_url, job_location. RemoteOK and We Work Remotely jobs are filtered by keyword_list. Jobs are then deduped by URL, or by company plus title when there is no URL.

6. Resolve the LinkedIn company (If + Periodix Actions + Code)

Jobs from RemoteOK and We Work Remotely have no LinkedIn company ID. For those, a Periodix Actions Search runs a LinkedIn company search by name:

The top 3 results are compared to the job's company by normalized name, not just the first result. The outcome is written to company_match:

company_matchMeaning
has_idThe job came from LinkedIn with a company ID
verifiedA company page name matched
unverified_fallbackNo name matched, the top result was used
not_foundNo company results

7. Score Fit with AI and Keep Strong Fits (HTTP Request + Code + Filter)

AI scores each job 1 to 10 against your profile and preferences, and classifies work_mode as REMOTE_OK, HYBRID_OK, HYBRID_TOO_FAR, or UNCLEAR. Only jobs with fit_score of 5 or higher that are not HYBRID_TOO_FAR move on.

8. Draft Application with AI (HTTP Request + Code)

Writes a short application note under 600 characters, specific to the role and your background. Saved as application_note.

9. Find Recipient at Company (Periodix Actions: Search + Code)

For every job with a company ID, a people search runs inside that company:

{{ "https://www.linkedin.com/search/results/people/?keywords=" + encodeURIComponent($('Search Config').first().json.recipient_titles) + "&currentCompany=%5B%22" + $json.company_id + "%22%5D" }}

From up to 10 results, the workflow picks the first person whose headline contains one of your recipient_titles. The outcome is written to recipient_match: verified, unverified_fallback, not_found, or skipped (no company resolved).

10. Draft Connection Note and Send Connection Request (HTTP Request + Periodix Actions: Connection)

AI writes a connection note under 300 characters that mentions the specific role. Then Periodix Actions sends it:

  • Resource: Connection
  • Operation: Send Request
  • Recipient: {{ $json.recipient_id }}
  • Note: {{ $json.connection_note }}

11. Save Leads (Google Sheets)

Every strong-fit job is appended to the Leads tab, whether a request was sent or not, with connection_sent set to true or false.

Example output (Leads tab row)

{
  "source": "remoteok",
  "job_title": "Growth Marketing Manager",
  "company_name": "Example Labs",
  "company_id": "12345678",
  "company_match": "verified",
  "job_url": "https://remoteok.com/remote-jobs/example",
  "job_location": "Remote",
  "fit_score": 8,
  "work_mode": "REMOTE_OK",
  "fit_reason": "Matches wanted growth role, fully remote, B2B SaaS.",
  "application_note": "Hi, I am applying for the Growth Marketing Manager role at Example Labs...",
  "recipient_name": "Sam Lee",
  "recipient_headline": "Talent Acquisition Lead at Example Labs",
  "recipient_id": "ACoAAExample789",
  "recipient_match": "verified",
  "connection_note": "Hi Sam, I just applied for the Growth Marketing Manager role at Example Labs and would love to connect.",
  "connection_sent": true
}

Customization

  • Who to reach: set recipient_titles to Recruiter for a warm intro, CEO or CTO to go straight to the top, or list several.
  • Confirmed matches only: filter the Sheet on company_match and recipient_match to skip unverified_fallback rows, or add an If node before Send Connection Request that only allows verified.
  • Review before sending: remove Send Connection Request and send manually from the Sheet.
  • More job boards: copy the RemoteOK or We Work Remotely branch and normalize to the same fields.

Troubleshooting

  • No LinkedIn jobs: check linkedin_geo_id, widen freshness_hours, or simplify job_keywords.
  • No RemoteOK or We Work Remotely jobs: your keyword_list is too narrow for their titles and tags.
  • recipient_match is not_found for most jobs: list fewer titles in recipient_titles. LinkedIn keyword search works best with one or two terms.
  • Outreach columns are empty in the Sheet: add the column headers listed in What you need. The Sheets node maps fields by header name.
  • Scores of 0 with reason "parse error": the AI reply was not valid JSON. Check the model name and API key.
  • The same job appears on different days: the workflow dedupes within one run only. Read the Leads tab first and filter by job_url, or use Append or Update matched on job_url.

Related


Did this page help you?