HubSpot Reporting for Recruiters: Dashboards That Work

TL;DR: HubSpot reporting for recruiters fails on the schema underneath it, not on the report builder. Time-to-fill, source-of-hire and BD-to-placement conversion all require two separate deal pipelines, one for BD and one for candidates, associated to the same Company record, plus custom properties for Source of Application, Placed Date, Vacancy ID, Vacancy Type and Fee Value, and a custom association label between Contacts and Deals. None of that can be applied retrospectively, so it has to be built before the data goes in. HubSpot has no native vacancy, placement or candidate object, and past roughly five consultants running perm and contract together, a third-party layer such as Databox is usually cleaner than configuring around the limits.
Why do most recruitment firms get HubSpot reporting wrong?
Most recruitment firms build a deal pipeline that mirrors their recruitment stages, then find six months later that the report they want cannot be built at all. The cause is using deal stage as a proxy for both vacancy status and candidate progression without a defined property schema, so the stage label carries the meaning and the underlying data does not. HubSpot's custom report builder joins objects through defined associations, and where those associations and properties were never created, no amount of dashboard configuration recovers the metric.
The pattern I see repeatedly: a firm implements HubSpot, builds a deal pipeline that mirrors their recruitment stages - Briefed → Candidates Sent → Shortlisted → Placed - and it looks correct. Six months in, someone asks "what's our average time-to-fill?" and there's no way to answer it from the data that exists.
The root cause is using deal stage as a proxy for both vacancy status and candidate progression without a defined property schema. The two things become tangled. You can no longer distinguish "this deal moved to Shortlisted because a candidate was shortlisted" from "this deal moved to Shortlisted because the client reviewed the CVs." The stage label carries the meaning. The data doesn't.
A specific failure mode worth naming: no Source of Application property on Contact or Deal at point of entry means source-of-hire attribution is permanently lost. You cannot retrospectively tag it. The data was never captured, so no report can surface it.
Most firms respond by going looking for the right report. The right report is structurally impossible to build because the upstream schema doesn't support it. HubSpot's custom report builder joins objects via defined associations. If those associations weren't built into your pipeline setup, you cannot pull those metrics now. That is a data modelling problem, not a dashboard configuration problem.
The three reporting layers a recruitment firm actually needs
Before touching any report configuration, it's worth being clear about who the reports are for. There are three distinct layers, and conflating them is the second most common mistake after the schema problem.
BD and client reporting - pipeline value by stage, vacancy win rate (vacancies briefed vs. filled), client conversion rate from prospect to retained or exclusive. Audience: BD director, MD.
Delivery reporting - candidate pipeline velocity, time-in-stage per vacancy, drop-off point analysis showing where candidates fall out of the process. Audience: delivery lead, billing manager.
Activity reporting - calls made, CVs submitted, interviews booked, offers extended per consultant per week. Audience: line managers, ops.
A delivery consultant looking at a dashboard that includes weighted pipeline revenue is seeing noise. A BD director looking at average CV-to-interview conversion is also seeing noise. One dashboard built to serve both audiences serves neither.
The conflation problem shows up in a specific way: a firm builds one pipeline where "Shortlisted" means both "client has been given CVs" and "candidate has been shortlisted." When you filter by stage in a report, you're pulling both meanings into the same row. The numbers look plausible. They're meaningless.
Separating reporting by audience also means separating dashboard permissions where possible. Consultants don't need visibility of margin figures or total pipeline revenue. That's occasionally a data privacy issue, and it's always a distraction from the metrics that are actually relevant to them.
How should you set up pipelines and properties so HubSpot reports are possible?
Reporting starts with two separate deal pipelines: a BD pipeline tracking the client and vacancy relationship, and a candidate pipeline tracking each placement attempt, with both associated to the same Company record. On the candidate pipeline, Source of Application, Placed Date, Vacancy ID and Fee Value need to exist as custom properties, agreed and created before any data goes in. The piece most firms miss is a custom association label between Contacts and Deals, without which no report can tell a candidate apart from a client contact on the same deal.
The two-pipeline structure
What I'd do from the outset is build two separate pipelines in HubSpot Deals:
BD pipeline - stages map to client and vacancy development: Prospecting → Briefed → T&Cs Agreed → Vacancy Filled / Lost. This tracks the commercial relationship with the client.
Candidate pipeline - stages map to candidate progression: Identified → Submitted → Interviewed → Offered → Placed / Rejected. This tracks each placement attempt.
Both pipelines associate to the same Company record in HubSpot. That association is what makes the BD-to-placement conversion report possible later. If the two pipelines are pointing at different company records, or if the company association is missing from one of them, that report becomes impossible to build without manual reconciliation.
The custom properties you need before you start
On Deals in the candidate pipeline, you need at minimum:
Source of Application - dropdown, populated at point of submission. Options: job board, referral, database search, LinkedIn, direct application. Agree the list before you create the property - changing dropdown options later doesn't update historical records.
Placed Date - date property, set when the deal moves to Closed Won. HubSpot's native Close Date field works, but a custom Placed Date property is cleaner if your close date is being used for other purposes.
Vacancy ID - single-line text or number, cross-referencing the BD pipeline deal or, for firms using Bullhorn, the Bullhorn vacancy ID. This is the join key if you ever need to reconcile data between systems.
Fee Value - currency property, separate from the Deal Amount field. For contingency-based firms, deal amount is often blank or estimated at creation. Fee Value gets populated at placement and gives you accurate revenue reporting.
On associations: set up a custom association label between Contacts and Deals - Candidate: Placed alongside the default association. This is the thing most firms skip, and it's the point where HubSpot reporting for recruiters breaks down in practice. Without a custom association label, you cannot filter in the custom report builder to distinguish "candidate associated to this deal" from "client contact associated to this deal." HubSpot's default association model doesn't carry that distinction natively. There is no workaround for this - you either have the association label or you don't.
One more thing worth flagging on the candidate pipeline: time-in-stage tracking only works correctly if stage names are consistent and the deal has actually moved through stages sequentially. Deals bulk-created directly at a later stage will show 0 days for every earlier stage. That's a data quality issue that will permanently skew your time-in-stage averages if it's widespread.
Which reports are worth building in HubSpot for a recruitment firm?
Five reports cover what a recruitment firm actually needs out of HubSpot: time-in-stage by pipeline, source-of-hire attribution, BD-to-placement conversion by client, consultant activity against outcome, and vacancy fill rate over time. All five are built in the custom report builder rather than the standard reports, because HubSpot has no native time-to-fill or source-of-hire metric to draw on. Each depends on properties and associations existing before the data was created, so a missing field means a missing report rather than a slower one.
1. Time-in-stage by pipeline
Use the deal stage duration report in the custom report builder, filtered to the candidate pipeline only. Group by pipeline stage, with average days in stage as the metric. Filter by Deal Owner to cut it by consultant.
Worth knowing: this report shows current stage duration for deals still in that stage, plus completed stage duration for deals that have moved on. Deals created directly at a later stage - bulk imports, for example - will show 0 days for earlier stages. That's a data quality problem, not a report configuration problem.
2. Source-of-hire attribution
Built from the Source of Application property on Deals in the candidate pipeline. Build it as a funnel breakdown: total submissions by source, through to Placed. This tells you which source produces candidates that actually complete the process versus sources that drop out at interview stage.
This report requires Source of Application to have been populated consistently from day one. If it wasn't, you'll get a large "unknown" or blank category that makes every percentage in the report unreliable. There's no way to recover that data retrospectively.
3. BD-to-placement conversion by client
Cross-reference Associated Company data against Closed Won deals in both pipelines. The metric: of the vacancies a client briefed (BD pipeline Closed Won), what percentage resulted in a placement (candidate pipeline Closed Won, same associated company)?
This is the report recruitment MDs actually want. It identifies which clients fill their vacancies and which ones consume consultant time without converting. It requires both pipelines to be associated to the same Company record - which is why the two-pipeline structure matters from the start.
4. Consultant activity vs. outcome
Calls and meetings logged in HubSpot's activity log, compared against placements made in the same period, by Deal Owner. This report surfaces the ratio of activity to result. A consultant making 50 calls a week and placing once is a different problem from a consultant making 15 calls and placing twice.
The caveat: this only works if call logging is actually being done in HubSpot. If consultants are dialling from their mobile and not logging the call, the activity data is incomplete. That's a behaviour problem, not a system problem. The report will look like certain consultants are doing very little activity when they're actually just not logging it. Don't mistake the reporting gap for a performance gap without checking first.
5. Vacancy fill rate over time
Uses the Placed Date custom property on candidate pipeline deals, calculated against the Create Date of the associated BD pipeline deal or the vacancy creation date if you're using a Vacancy ID. HubSpot doesn't have a native "time-to-close from vacancy open" metric - you're building it from two date properties and the custom report builder.
Set Placed Date as the x-axis in a line chart and trend it over time. This is useful for demonstrating delivery speed improvement or deterioration across quarters, and it's one of the first things a client MD will ask for once the basic dashboards are live.
Where does HubSpot's reporting genuinely fall short for recruiters?
HubSpot is not built for recruitment. There is no native object for a vacancy, a placement, or a candidate. Everything is adapted from generic CRM objects, and the reporting reflects that. Being clear about the limitations upfront saves a lot of time later.
Limitation 1: cross-object joins require defined associations. If the association doesn't exist in your schema, the join is impossible in the custom report builder. There is no workaround. You either built the association into the pipeline setup or you didn't. This catches firms who configured their pipelines quickly, without thinking about what they'd need to report on six months later.
Limitation 2: forecast reports are revenue-weighted. For contingency recruitment firms where fee value isn't confirmed until a placement is made, deals can sit at £0 for months. The weighted pipeline figure in HubSpot's forecast view will consistently understate what's actually in play. It's not a bug - it's how the feature is designed - but it makes the forecast view actively misleading for contingency desks.
Limitation 3: some standard report types lock to a single pipeline. If you want to compare candidate conversion rates across permanent and contract pipelines in one view, you need the custom report builder, not the standard reports. Some firms build their dashboards using standard reports, get everything looking right, and then discover they need to rebuild reports they thought were finished when they try to create a cross-pipeline view.
A specific failure mode that comes up more than it should: firms use Deals Created to track new vacancies and later realise they can't filter by vacancy type - perm, contract, interim - because they never created a Vacancy Type property. The data is buried in the deal name, where it's not queryable in any report. By the time this is discovered, there may be hundreds of deals with no structured vacancy type data.
When should you bring in a third-party reporting layer?
The practical threshold where HubSpot's dashboard builder starts producing workarounds rather than clarity: more than 5 consultants, running perm and contract simultaneously, needing blended BD and delivery reporting in the same view. At that point, pulling data out of HubSpot and presenting it elsewhere is often cleaner than trying to configure your way around the native limitations.
Two options worth naming:
Databox - integrates directly with HubSpot via a native connector. Pulls HubSpot metrics into KPI-style dashboards that are readable by people who don't log into HubSpot - MDs, ops, board. Good for weekly performance snapshots. The limitation is that it reads HubSpot's data model as-is. If the properties aren't clean in HubSpot, Databox can't fix them. It will faithfully report your bad data in a much nicer format.
HubSpot to Google Sheets via the native integration - useful for firms that already work in Sheets and want to build custom calculations the HubSpot report builder can't handle, such as blended margin or banded fee calculations. The sync is list-based rather than real-time, so it's suited to weekly reporting, not live dashboards.
For firms running HubSpot and Bullhorn in parallel: the cleanest approach is usually to keep candidate data in Bullhorn and BD data in HubSpot and report on each system separately. Trying to join the two in HubSpot's dashboard requires a custom integration and a very clean Vacancy ID cross-reference throughout both systems. It is achievable, but it adds meaningful complexity and ongoing maintenance overhead. Worth being honest about that before committing to the approach.
A practical checklist before you build any HubSpot report
This is what I check before touching the report builder on any new client engagement. If the answer to any of these is no, the reports that follow will either be wrong or incomplete.
Correct pipeline structure exists. BD pipeline and candidate pipeline are separate, stage names are consistent, and - critically - no stage names have been renamed mid-project. Renaming a stage in HubSpot breaks historic stage duration data for any deal that passed through that stage before the rename. The old name disappears from the record.
Required custom properties are created and labelled consistently. Source of Application, Placed Date, Vacancy Type, Fee Value. Check that dropdown options match across the team. One person writing "LinkedIn" and another writing "linkedin" produces two different filter values in every report that uses that property.
Association types between objects are defined. Custom association labels are in place between Contacts and Deals (Candidate: Placed), and between BD pipeline deals and candidate pipeline deals where relevant. If this wasn't set up at the start, it cannot be applied retroactively to historical records.
Historical deal data has been populated. Blank fields don't appear as zero in reports - they disappear from the dataset entirely. A deal with no Source of Application value won't show as "unknown" by default. It simply won't appear in the source breakdown. This skews every percentage in any report that uses that field, and the skew gets worse the older the data is.
Correct team and owner filters are in place. Consultant-level reports need to be scoped to the correct team. A cross-team view at consultant level is usually displaying the wrong data and occasionally a data privacy issue if margin or salary figures are visible to people who shouldn't see them.
If you're not sure whether your current HubSpot setup passes this checklist, a revenue operations audit covers this as part of the initial assessment - looking at pipeline structure, property schema, and association configuration before making any recommendations about what to build.