was fairly reactive. I'd submit applications, wait for responses, and then act on whatever came back. As the number of applications grew into the hundreds, that approach quickly became unsustainable.
Tracking applications manually in a spreadsheet helped at first, but it introduced a new set of problems. Every application meant tabbing across multiple columns, entering the same information repeatedly, updating statuses by hand, and trying not to accidentally overwrite or misalign rows. It worked, but it was tedious, time-consuming, and became increasingly difficult to maintain.
Looking back, one thing I would recommend to anyone beginning a job search is creating a dedicated email address. Keeping recruiting emails separate from your personal inbox makes organization much easier. But even with a dedicated inbox, the real challenge remains: how do you efficiently manage all of the information that comes with a large-scale job search?
That led me to ask the same question I ask with almost every operational challenge: How can we automate this?
Rather than making Google Sheets the application I interacted with every day, I wanted it to become the database running quietly in the background. My goal was to build custom HTML interfaces for entering and updating information, while using Looker Studio to visualize progress and analytics. Google Sheets would simply store the data, Google Apps Script would handle the business logic, and the user experience would be built around tools that were faster, cleaner, and much easier to use.
That shift transformed Google Sheets from a spreadsheet into the backend of a lightweight applicant tracking system built specifically around my workflow.
This was the first iteration of the page. It was intentionally simple and optimized for speed. Fields like Status and Date were filled in automatically, so all I had to enter was the company name, role, salary (if listed), and the job posting URL.
One feature I really liked was a duplicate check. If I entered a job posting URL that already existed in my tracker, it would immediately alert me. That prevented duplicate applications and reminded me to check the status of an application I'd already submitted instead of starting over.
This next iteration came after I changed how I approached my job search. Instead of simply applying to as many jobs as possible, I wanted to be more intentional and collect better data along the way.
One of the biggest improvements was realizing that some information, like the application date and initial status, could be recorded automatically in the background. That kept the form simple while still capturing useful information.
I also added a few new fields, including the date the job was posted, the company's industry or vertical, and LinkedIn context. Those additions made it much easier to follow up with recruiters, revisit opportunities, and better track my overall job search.
This is the current version of the tool as it exists today: still simple to use, but much more powerful behind the scenes.
The last part of the process I wanted to improve was updating application statuses. Even after I slowed down and became more intentional with my applications, manually searching through my inbox for rejection emails and updating my tracker was still tedious.
To solve that, I built an automated Apps Script that scans my inbox on a weekly basis and looks for common indicators that a company has decided not to move forward. It automatically updates applications that are still in the "Applied" stage, where I haven't spoken with a recruiter or interviewer yet.
Once I'm actively interviewing with a company, I still update those statuses manually. I actually think that's the right balance, since those opportunities require more context anyway. But for the majority of applications, the automation eliminates the repetitive task of digging through emails and keeping everything up to date by hand.