Searching for jobs in today’s age of AI and fake job postings can be exhausting. Without a referral or “knowing a guy” you’re stuck cold applying to companies that are likely using AI tools to filter results. The landscape has changed dramatically, but that doesn’t mean all is lost. In fact, you can employ the same AI tools large companies use to help you scale your job search efforts. Instead of spending hours combing through postings on Indeed, let Google Workspace Studio search for openings and create a database for you.

Here’s what you’ll need to get started:

  • Google Sheets: This will be your database.
  • Google Workspace Studio: This is the automation engine that searches jobs and populates your database.
  • Google Apps Script (optional): This will be used to format the data from Gemini.

How It Works

Google Workspace Studio passes the below prompt into Gemini. Feel free to tweak it to suit your needs. However, if you change the column names, you’ll need to do so in Apps Script. More on that later.

The Prompt

Role:
You are a Professional Technical Recruiter and Data Analyst specializing in Remote CRM and Automation roles. All roles must be United States based and fully remote.

Objective:
Scrape and identify active, remote-only job listings for the following roles:
CRM Developer (Dynamics / Salesforce)
CRM Admin
IT Director
Business Systems Admin / Developer
Python Developer
Automation Engineer
Power Automate / Power Apps Developer

Data Requirements:
Search across LinkedIn, Indeed, and specific company Careers pages.
Only include actual job listings with verifiable details.
If a specific data point (such as Phone or Email) is not listed, enter "N/A".
For Salary, only use the range explicitly stated in the job listing.
Provide the Direct Job Link (the URL where the application lives).

Formatting Rules (CRITICAL for Automation):
Output each job using the exact label format below.
Every line must end with a pipe symbol (|) so a Google Sheets script can parse the data.
Do not include any introductory or concluding text.
Start immediately with "Company:"

Company: [Name] |
Job Title: [Text or N/A] |
Phone Number: [Number or N/A] |
Email: [Email or N/A] |
Description: [2-3 sentence summary of core duties] |
Salary Range: [Amount or N/A] |
Date Posted: [Date or Timeframe] |
Keywords for Resume: [Comma separated list of tech stack/skills] |
Job Link: [Full URL] |

Once this prompt is passed into Gemini it’ll start searching for jobs and contracts in accordance with the guidelines you defined. Once it’s done its work, you’ll get a notification via email letting you know it’s found new opportunities.

Next, it takes the information it found and adds it into a Google Sheets doc for review. Finally, this part is optional. Apps Script takes that giant block of text and splits it into human-readable columns and rows. Here’s a high-level overview of the process.

  • At a predefined interval your prompt is passed to Gemini.
  • Gemini executes your job search.
  • It deposits results in a spreadsheet.
  • You receive an email letting you know there are new opportunities to review.
  • Apps Script cleans up the extracted data.

Google Sheets: The Database

This is going to serve as your CRM. All your prospects will be stored here along with their names, email addresses, salary ranges, job titles, and more. At a minimum you’ll want to structure the table housing your data as follows:

Company
Phone Number
Email
Description
Salary Range
Date Posted
Keywords
Job Link

Google Workspace Studio: The Automation Engine

While not as robust as tools like Power Automate and n8n, Google Workspace Studio has just enough functionality and integrations to make some seriously useful workflows. It is the engine that powers the data extraction and entry. A task that takes hours for us humans to do and is extremely error-prone as you pile on more data.

Once you’ve created the spreadsheet, it’s time to include it in your flow.

Note: Make sure you create the spreadsheet within the same account Workspace Studio resides in.

Here’s an overview of the Job Extraction workflow.

  • On a schedule: I like to set this after my workouts during the week. So mine comes in at 7:30 AM.
  • Ask Gemini: Using the prompt I gave you above, Gemini will start its job search.
  • Notify me by email: I prefer email but you have the option of getting a message on Google Chat as well.
Workflow Setup in Google Workspace Studio

Add a row: This is where prospects are stored. Be sure to choose the right sheet if you have multiple. And, if you’re keen on preserving history, choose the ‘After last data row’ option in the Add row section.

Email from Job Search notification example

Cleaning and Formatting Data: Apps Script (optional)

This step is optional but recommended so your data doesn’t come in as giant blocks of text. To enable Apps Script in your Sheets, select the Extensions option in the top menu. Next, click Apps Script.

Open Apps Script from Google Sheets

Next, you’ll be taken to the Apps Script editor and given some boilerplate JavaScript code. Delete that and replace it with this.

/**
* Adds a custom menu to the Google Sheet toolbar.
*/
function onOpen() {
 const ui = SpreadsheetApp.getUi();
 ui.createMenu('Job Portal')
   .addItem('Sync All Jobs Now', 'processFullJobSuite')
   .addToUi();
}


/**
* Main Function:
* 1. Finds raw data in Column A.
* 2. Extracts fields based on your Gemini template.
* 3. Appends new unique jobs to the bottom.
* 4. Deletes the original raw data rows to remove gaps.
*/
function processFullJobSuite() {
 const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  // 1. Setup Headers (only if row 1 is empty or missing headers)
 const headers = ["Company", "Job Title", "Phone Number", "Email", "Description", "Salary Range", "Date Posted", "Keywords", "Job Link", "Reliability Score"];
 if (sheet.getLastRow() === 0 || sheet.getRange(1,1).getValue() === "") {
   const headerRange = sheet.getRange(1, 1, 1, headers.length);
   headerRange.setValues([headers]);
   headerRange.setFontWeight("bold").setBackground("#f3f3f3").setVerticalAlignment("middle");
 }


 // 2. Map existing Job Links to prevent duplicates
 // We look at Column I (Index 8) where the Job Link is stored
 const currentValues = sheet.getDataRange().getValues();
 const existingLinks = currentValues.map(row => row[8] ? row[8].toString().toLowerCase().trim() : "");
  let allExtractedRows = [];
 let rowsToDelete = [];


 // 3. Iterate through rows from BOTTOM to TOP
 // This is critical for deleting rows without messing up the numbering
 for (let i = currentValues.length - 1; i >= 1; i--) {
   let cellContent = currentValues[i][0].toString();
  
   // Check if the cell contains the keyword "Company:"
   if (!cellContent || !cellContent.includes('Company:')) continue;


   // Split cell into individual job blocks (handles multiple jobs in one cell)
   let jobBlocks = cellContent.split(/(?=Company:)/g);


   for (let block of jobBlocks) {
     if (block.trim() === "" || !block.includes(':')) continue;


     // Helper function to extract text after a label and before a pipe or newline
     const getVal = (label) => {
       const regex = new RegExp(label + ":\\s*([^|\\n]+)");
       const match = block.match(regex);
       return match ? match[1].trim() : "N/A";
     };


     let jobLink = getVal("Job Link");
     let uniqueKey = jobLink.toLowerCase().trim();


     // DUPLICATE CHECK: Skip if this URL is already in our list
     if (jobLink !== "N/A" && existingLinks.includes(uniqueKey)) continue;


     let company = getVal("Company");
     let jobTitle = getVal("Job Title");
     let phone = getVal("Phone Number");
     let email = getVal("Email");
     let description = getVal("Description");
     let salary = getVal("Salary Range");
     let datePosted = getVal("Date Posted");
     let keywords = getVal("Keywords for Resume");


     // Calculate Reliability Score
     let score = 0;
     if (company !== "N/A") score += 20;
     if (jobTitle !== "N/A") score += 20;
     if (salary !== "N/A") score += 20;
     if (jobLink !== "N/A") score += 20;
     if (description.length > 50) score += 20;


     allExtractedRows.push([
       company,
       jobTitle,
       phone,
       email,
       description,
       salary,
       datePosted,
       keywords,
       jobLink,
       score + "/100"
     ]);
   }
   // Mark this row for deletion
   rowsToDelete.push(i + 1);
 }


 // 4. Append the extracted jobs to the bottom of the table
 if (allExtractedRows.length > 0) {
   const startRow = sheet.getLastRow() + 1;
   // We reverse it back because we collected them while looping backwards
   allExtractedRows.reverse();
  
   const outputRange = sheet.getRange(startRow, 1, allExtractedRows.length, headers.length);
   outputRange.setValues(allExtractedRows);
  
   // Formatting for readability
   outputRange.setVerticalAlignment("top").setWrap(true);
   sheet.autoResizeColumns(1, headers.length);
   sheet.setColumnWidth(5, 400); // Set Description width to 400px
 }


 // 5. Delete the original raw rows (removes white space/gaps)
 if (rowsToDelete.length > 0) {
   rowsToDelete.forEach(rowNum => {
     sheet.deleteRow(rowNum);
   });
 }
}

Hit CTRL + S or CMD + S to save your script. Next, click the Triggers option.

Time Triggers menu in Apps Script

Select the +Add Trigger button. Next, fill in the fields as outlined below.

Time Trigger Configuration in Apps Script

The purpose of this section is to tell Apps Script to run the processFullJobSuite function every minute on the data in your Job Search database. Finally, if it fails for any reason, it needs to notify you each time. The most common reason for failure is altering the column names or table structure. The names of the columns are hard-coded in, so changing them results in your code getting confused and bombing out.

Why is this better than job alerts

You might be wondering why you should go through all of this instead of subscribing to job alerts from the various sites. There are two important reasons to go this route over the native subscriptions to Indeed, Glassdoor, etc. Privacy and Efficiency. The first reason is arguably the most important.

Each time you log into one of these sites, your information is tracked and depending on the site, sometimes sold. This results in dozens of unsolicited emails, calls, and text messages. It’s a gross violation of privacy and can be very risky from a security perspective. By employing this automation, job sites aren’t tracking you. Instead, you are tracking job sites.

You cherry-pick the companies you actually are interested in and provide them with your resume and contact information when you feel comfortable doing so. This is not only secure but highly efficient. You control what types of jobs you want to see by allowing Gemini to filter out ones that aren’t a good fit for you.

Once prospects are found, a database is filled with leads you can start contacting. Instead of blindly spamming resume uploads, you are conducting targeted searches on qualified leads. You regain control of the job hunt by creating a sales pipeline.

Automate your way into a bigger bank account

Companies are adopting AI at a record pace. To stay competitive and relevant in the job market, you’ll need to do the same. While many automation tools like Power Automate and UI Path are expensive and complicated, Google Workspace Studio is extremely easy to use and relatively inexpensive. Take advantage of enterprise-grade automation and AI with Gemini and take your job hunt to the next level.

If you’re interested in automating more of your workday, check out how I built a free alternative to SEMRush vibe coding with Google’s AI Studio. Read it here.