# Recruiting analytics dashboard for every open Breezy HR role

> See every open role, where candidates are stalling, and which sources actually produce hires, then export the numbers to Google Sheets.

- Workflow type: app
- Services: Breezy HR, Google Sheets
- Categories: HR & People, Operations
- Published: 2026-08-14

## What it does

- Lists every open role with live candidate counts by stage, how long the role has been open, and a funnel bar showing where people drop off
- Drills into any role to show stage by stage conversion and the average time candidates spend in each stage
- Flags candidates who have been sitting in one stage too long, using a threshold you set, so nobody quietly goes cold
- Breaks down candidates by source so you can see which channels produce actual hires instead of just applications
- Exports whatever you are looking at to a Google Sheets tab with one click, ready to paste into a board deck

## What you'll need

- A Breezy HR account that can see the positions and candidates you want to analyze
- A Breezy HR sign in that does not require a two factor code, since the connection uses your email and password
- A Google account and a spreadsheet you want the exports to land in
- At least one open role with candidates in it, so the funnel has something to measure

## Prompt

Build me an interactive recruiting analytics app on top of Breezy HR that answers the questions Breezy's own reporting cannot: where candidates are stalling, and how each open role is really tracking. The audience is our recruiting lead and head of people. They open it weekly before pipeline reviews and monthly when they need real numbers for an exec deck. This is a dashboard someone explores, not a scheduled report, so nothing should run on a timer or message anyone.

Data loading. Resolve the company once at startup with List Companies, then do all reads in server side handlers. Use List Positions filtered to open roles, List Candidates for Position for each role, and Get Pipeline to get the canonical stage list and its correct order. Every chart and table must order stages the way Get Pipeline defines them, never alphabetically or by count. Breezy's list endpoints return the full array with no cursors, apart from candidate search, so fetch complete sets in the handler and aggregate server side rather than paging in the UI. Keep the request rate under roughly 5 per second, throttle the fan out across positions and candidates, and on a 429 wait for the reset header and retry once. Cache the aggregates for the session and give the user a manual refresh button.

Landing view: every open position. Show the role title, department and location, days open computed from the position creation date, total active candidates, the count sitting in each stage, and a horizontal funnel conversion bar segmented by stage in pipeline order so drop off is visible at a glance. Let the user sort by days open, candidate volume, or number of stalled candidates, and filter by department. Clicking a role opens its detail view.

Role detail view. Show stage by stage conversion, meaning the pass through rate between each pair of consecutive stages plus the cumulative rate from first application, and the average and median time candidates spend in each stage. Important implementation note: time in stage is not a field on the candidate. Derive it from the stage change entries in Get Candidate Stream. For each candidate on the position, pull their stream, keep the stage change events, sort them chronologically, and measure the interval between consecutive changes. For the stage a candidate currently sits in, measure from their most recent stage change to now. Fetch these streams concurrently but rate limited, and show a loading state since this is the slowest part of the app.

Stalled candidates panel inside the role detail view. List every candidate who has been sitting in a single stage longer than a configurable threshold, defaulting to 10 days, showing name, current stage, days in stage, and the date of their last activity from the stream. The threshold is an app setting the user can change, it persists between sessions, and the flagged list recalculates immediately when it changes. Where a candidate has no recorded stage changes, show not enough data rather than zero days.

Source breakdown view. Group candidates across all open roles by their source field and show, per source, total candidates, how far they get as counts by furthest stage reached, hires, and the conversion rate from applicant to hire. The point is to reveal which channels produce hires rather than which produce volume, so sort by hire rate by default and let the user filter to a single position or a date range.

Export. Put an Export button on every view that writes exactly what the user is currently looking at, including their active filters and threshold, to a Google Sheets tab using Append Values. Persist the spreadsheet id and tab name in app settings so repeat exports land in the same place, and if the tab does not exist yet create it first with Batch Update Spreadsheet. Write a header row plus one row per record, stamp every exported row with the export timestamp and the view it came from, and append below existing rows so past exports are preserved. Use the user entered input option so numbers, percentages, and dates arrive as real values a recruiting lead can chart, not as text.

Handle empty states properly throughout: a role with no candidates, a stage nobody has reached, and a stream with no stage changes should all render a clear message instead of a broken chart or a misleading zero.

## How to customize

- Change the stalled threshold from 10 days to whatever your team considers slow
- Point exports at a different spreadsheet or tab, for example a fresh tab each month
- Choose which roles appear, such as only open roles or only one department
- Sort the role list by days open, candidate volume, or number of stalled candidates

## FAQ

### How is this different from Breezy HR's built in reporting?

Breezy shows you counts. This shows you movement. It works out how long candidates actually sit in each stage, which stage loses the most people, and which candidates have gone quiet, then lets you export any of it to a spreadsheet.

### How does it know how long a candidate has been in a stage?

Breezy does not store time in stage as a field, so the app reads each candidate's activity history and measures the gaps between their stage moves. Candidates with no recorded stage changes are shown as not enough data rather than zero days.

### Can I change the 10 day stalled threshold?

Yes. The threshold is a setting inside the app. Change it to 5, 14, or whatever matches your hiring pace, and the flagged list updates immediately. Your choice is saved for next time.

### Will exporting overwrite what is already in my spreadsheet?

No. Exports are added underneath the existing rows on the tab you choose, and each export is stamped with the date and the view it came from, so you keep a history instead of losing last month's numbers.

### Does anything get sent automatically on a schedule?

No. This is a dashboard you open when you need it, typically before a weekly pipeline review or a monthly exec update. Nothing emails your team or posts on its own.

Use this prompt in General Input: https://www.generalinput.com/prompts/recruiting-analytics-dashboard-for-every-open-breezy-hr-role