Gmail + Google Sheets: resumes scored and logged
Your inbox shouldn’t be your applicant tracking system. But when resumes arrive as PDFs in Gmail, it’s easy to lose track, forget who applied for what role, or end up “saving” files in five different places.
This Gmail resume scoring automation hits recruiters first, honestly. HR generalists and founders hiring between meetings feel it too. The outcome is simple: every resume gets stored, scored, and logged so you can review top fits fast without manual copy-paste.
Below, you’ll see exactly how the workflow moves from a new email to a clean Google Sheet row, plus what you need to run it and the common pitfalls to avoid.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Gmail + Google Sheets: resumes scored and logged
flowchart LR
subgraph sg0["Inbox Attachment Watch Flow"]
direction LR
n0@{ icon: "mdi:play-circle", form: "rounded", label: "Inbox Attachment Watch", pos: "b", h: 48 }
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/airtable.svg' width='40' height='40' /></div><br/>Retrieve Job Listings"]
n2["<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/>Match Job From Subject"]
n3@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Match Found Check", pos: "b", h: 48 }
n4["<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/>Compose AI Prompt"]
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/merge.svg' width='40' height='40' /></div><br/>Initial Stream Merge"]
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/>Prepare Resume Files"]
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/httprequest.dark.svg' width='40' height='40' /></div><br/>Upload Resume File"]
n8["<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/merge.svg' width='40' height='40' /></div><br/>Unify Prompt And File"]
n9["<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/>Assemble Gemini Payload"]
n10["<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/>Request AI Analysis"]
n11["<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/merge.svg' width='40' height='40' /></div><br/>Aggregate Result Data"]
n12@{ icon: "mdi:cog", form: "rounded", label: "Archive To Drive", pos: "b", h: 48 }
n13["<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/>Parse AI Output"]
n14@{ icon: "mdi:database", form: "rounded", label: "Append To Sheet", pos: "b", h: 48 }
n3 --> n5
n3 --> n4
n8 --> n9
n5 --> n6
n1 --> n2
n7 --> n8
n11 --> n13
n2 --> n3
n12 --> n11
n0 --> n1
n0 --> n5
n13 --> n14
n4 --> n8
n4 --> n11
n9 --> n10
n6 --> n7
n6 --> n12
n6 --> n11
n10 --> n11
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 n0 trigger
class n3 decision
class n1,n14 database
class n7,n10 api
class n2,n4,n6,n9,n13 code
classDef customIcon fill:none,stroke:none
class n1,n2,n4,n5,n6,n7,n8,n9,n10,n11,n13 customIcon
The Problem: Resume screening turns into inbox chaos
When applications come in by email, the process looks “fine” until you’re buried. One candidate emails twice with updated PDFs. Another forgets to include the job title. You download attachments to your desktop, then re-upload them later, then try to remember which spreadsheet row matches which file. Meanwhile, hiring managers ask, “Any good ones yet?” and you’re still sorting subject lines. The real cost is not just time. It’s missed follow-ups, inconsistent evaluation, and decisions made from incomplete notes.
It adds up fast. Here’s where it breaks down in real teams.
- Someone has to read each email subject and guess which open role it belongs to.
- Resume files get downloaded and re-saved, which creates duplicates and broken links.
- Scoring is inconsistent because it depends on who had time to review that day.
- Google Sheets updates lag behind reality, so the “pipeline view” can’t be trusted.
The Solution: Automatically score Gmail resumes and log them to Sheets
This workflow watches your Gmail inbox for new emails that include resume attachments (PDFs). As soon as one arrives, it pulls the job title from the email subject and checks it against your open positions in Airtable, so the resume gets evaluated in the right context. The resume file is then stored in a designated Google Drive folder (so you have one clean source of truth), and the workflow sends both the file and a structured prompt to Gemini for analysis. Gemini returns a score, extracts key candidate details like name and phone, and adds a one-sentence explanation you can scan quickly. Finally, n8n appends everything into Google Sheets, including a download link to the stored resume.
The flow starts with Gmail, then Airtable provides job context, then Gemini produces a consistent evaluation. Google Drive stores the file, and Google Sheets becomes the “single list” your team can trust.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you get 20 resumes in a week across 3 open roles. Manually, you might spend about 10 minutes per resume downloading the PDF, renaming it, filing it in Drive, checking the role, and adding notes to a sheet, which is roughly 3 hours weekly. With this workflow, the “work” is basically opening the sheet later: Gmail triggers instantly, Drive storage and Gemini scoring run in the background, and the row appears automatically. You get your 3 hours back, plus a cleaner shortlist.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Gmail to receive applications and trigger runs
- Google Drive to store resumes in one folder
- Google Sheets to log candidates and AI scores
- Airtable for job listings and descriptions
- Gemini API key (get it from Google AI Studio)
Skill level: Intermediate. You’ll connect accounts, map a few fields, and paste in your job descriptions.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
New resume email hits your inbox. The workflow triggers from Gmail when a message arrives with an attachment, so nothing relies on someone remembering to check a folder.
Job context is pulled from Airtable. n8n fetches your open job listings and uses the email subject to match the candidate to the right role. If there’s no match, the workflow can stop early instead of scoring against the wrong job.
The resume is stored and prepared for AI. The PDF is uploaded and archived in Google Drive, and n8n composes a clear prompt that includes the job description and the evaluation criteria you care about.
Gemini scores and extracts the details. The workflow sends the resume file plus the prompt via HTTP Request, then parses Gemini’s response into structured fields like name, phone, score, and a short explanation.
Everything is appended to Google Sheets. A new row is created with candidate info, the AI score, feedback, and a Drive download link so review and sharing are frictionless.
You can easily modify the matching logic to use job codes instead of subject titles based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Gmail Trigger
Set up the workflow to watch for incoming emails with attachments so resumes are captured immediately.
- Add the Inbox Attachment Watch node as your trigger.
- Set Filters → q to
has:attachment. - Enable Options → downloadAttachments so the files are available downstream.
- Set Poll Times → item → mode to
everyMinutefor near-real-time ingestion. - Credential Required: Connect your gmailOAuth2 credentials.
Step 2: Connect Airtable and Match Jobs
Pull job listings and match the email subject to the most relevant role.
- Add Retrieve Job Listings and set Operation to
search. - Choose the Airtable Base and Table from your environment (e.g., “ResumeRadar” → “Job Descriptions”).
- Credential Required: Connect your airtableTokenApi credentials.
- Add Match Job From Subject and keep the provided JavaScript that computes similarity and a
MIN_SCOREthreshold of0.60. - Add Match Found Check and set the boolean condition to
{{ $json.matchFound }}equalstrue.
Match Found Check outputs to both Initial Stream Merge and Compose AI Prompt in parallel.
Step 3: Build the AI Prompt and Prepare Resume Files
Create a detailed prompt for Gemini and extract valid resume attachments.
- In Compose AI Prompt, retain the prompt template that injects EMAIL and JOB sections and returns strict JSON.
- Connect Initial Stream Merge to Prepare Resume Files to pass email payloads.
- In Prepare Resume Files, keep the allowed file types list set to
application/pdfand the binary property asdata. - Note the parallel split: Prepare Resume Files outputs to Upload Resume File, Archive To Drive, and Aggregate Result Data in parallel.
Step 4: Upload to Gemini and Request AI Analysis
Upload the resume file, assemble the model payload, and send the analysis request.
- In Upload Resume File, set URL to
https://generativelanguage.googleapis.com/upload/v1beta/files?uploadType=mediaand Method toPOST. - Set Content Type to
binaryData, Input Data Field Name todata, and include headers:x-goog-api-key={{$env.GEMINI_API_KEY}}andContent-Type={{ $json.mimeType || $binary.data.mimeType || 'application/octet-stream' }}. - Connect Upload Resume File and Compose AI Prompt into Unify Prompt And File so both inputs are merged.
- In Assemble Gemini Payload, keep the code that creates
bodywithresponseMimeTypeset toapplication/json. - In Request AI Analysis, set URL to
https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContentand JSON Body to{{$json.body}}. - Set the query parameter key to
{{$env.GEMINI_API_KEY}}and header Content-Type toapplication/json.
GEMINI_API_KEY environment variable—ensure it is set in n8n before testing.Step 5: Archive and Aggregate Results
Store the resume in Drive, combine streams, parse AI output, and prepare structured fields for your spreadsheet.
- Configure Archive To Drive with your target Drive and Folder.
- Set Name to the provided dynamic expression to create timestamped filenames:
{{ (function () { const email = ($json.fromEmail || 'unknown').toLowerCase(); const user = email.split('@')[0].replace(/[^a-z0-9._-]+/g,'-').replace(/^-+|-+$/g,''); const d = new Date(Number($json.internalDate) || Date.now()); const yyyy=d.getUTCFullYear(), mm=String(d.getUTCMonth()+1).padStart(2,'0'), dd=String(d.getUTCDate()).padStart(2,'0'), hh=String(d.getUTCHours()).padStart(2,'0'), mi=String(d.getUTCMinutes()).padStart(2,'0'), ss=String(d.getUTCSeconds()).padStart(2,'0'); const ext = (($json.fileName || '').split('.').pop() || ($json.mimeType==='application/pdf'?'pdf':'bin')).toLowerCase(); return `${user || 'unknown'}__${yyyy}-${mm}-${dd}-${hh}${mi}${ss}.${ext}`; })() }}. - Credential Required: Connect your googleDriveOAuth2Api credentials.
- Keep Aggregate Result Data set to Mode
combine, Combine BycombineByPosition, and Number Inputs4. - In Parse AI Output, retain the JSON parsing logic and output fields like
JobTitle,CandidateName,CandidateEmail,ResumeLink, andAIScore.
Step 6: Configure Output to Google Sheets
Append the structured screening results to a spreadsheet for tracking.
- Add Append To Sheet with Operation set to
append. - Select the target Document (e.g., “ResumeRadar - Applicants”) and Sheet (e.g., “Sheet1”).
- Map columns using the provided expressions such as
{{ $json.CandidateEmail }},{{ $json.CandidatePhoneNumber }}, and{{ '=HYPERLINK("' + $json.ResumeLink + '","Download")' }}. - Credential Required: Connect your googleSheetsOAuth2Api credentials.
Step 7: Test and Activate Your Workflow
Validate end-to-end execution and switch the automation to live mode.
- Click Execute Workflow and send a test email with a PDF resume attached to the monitored inbox.
- Confirm that Archive To Drive creates a file in your Drive folder and Append To Sheet adds a new row with the AI score and resume link.
- Check the Gemini calls in Upload Resume File and Request AI Analysis for successful 200 responses.
- Turn on the workflow with the Active toggle for production use.
Common Gotchas
- Google credentials can expire or need specific permissions. If things break, check the Gmail/Drive/Sheets credentials inside n8n’s Credentials page 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.
- Gemini API access can fail due to a missing key or billing restrictions. Confirm the key is set in n8n credentials or environment variables, then verify it in your Google AI Studio project.
Frequently Asked Questions
About an hour if your Airtable jobs and Google Sheet are ready.
No. You’ll mostly connect accounts and paste in your scoring criteria. The “code” nodes are already built into the workflow.
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 Gemini API usage costs.
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. You can adjust the subject matching in “Match Job From Subject” and expand your Airtable job table with department fields. Common tweaks include separate Drive folders per department, different Gemini scoring prompts per role, and extra columns in Google Sheets for hiring manager ownership.
Usually it’s expired OAuth access or missing Gmail permissions in your Google account. Reconnect the Gmail credential in n8n, then confirm the trigger is watching the right mailbox/label. If you’re using a shared inbox, make sure the account you authorized actually has access to it. Also check Google’s security alerts, because a password change can silently break older sessions.
A lot, as long as your n8n plan and Google/Gemini limits can keep up.
Often, yes, because this flow benefits from branching, merges, and handling files plus AI calls in one place. n8n also gives you a self-hosting option, which can matter when resume volume grows and per-task pricing starts to sting. Zapier or Make can still be fine if you only want “email arrives → add row,” with no job matching and no file storage discipline. The moment you need job context from Airtable and consistent scoring prompts, n8n tends to be easier to maintain long-term. Talk to an automation expert if you want help choosing.
Once this is running, your inbox stops being a hiring bottleneck. The workflow handles the repetitive sorting and scoring so you can spend your attention on actual interviews.
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.