Recruitment funnel
1. Dataset Name
recruitment_funnel
2. Description
A stage-level dataset that tracks each candidate's progress through the hiring pipeline, matching application stage events to standardized stage groups and adding hire status, match score, and source category. Each row represents one application at one stage, showing how long it spent there before moving to the next. This dataset powers recruitment funnel, stage conversion, time-in-stage, and source effectiveness reporting.
3. Source Tables
- customer_views.application_stage (aliased ast — primary stage event records per application)
- customer_views.stage_mapping (DISTINCT dedup CTE — maps customer stage names to standardized stage_group_index and ef_stage_group labels)
- customer_views.applications (aliased apps in application_hire_info CTE — provides hired_ts, match_stars, application_ts, and source_category derivation; also used in position_hire_flag CTE to flag positions with any hire)
- customer_views.positions (aliased pos — LEFT JOIN on position_id for position attributes, calibration flags, open/closed status, and creation_ts)
4. Grain
One row per application-stage combination. An application progressing through 5 stages will have 5 rows. The LEAD window function provides next_stage_ts and next_stage_group on each row, enabling days_in_stage_group to be computed inline without a self-join.
5. Dashboards Supported
- Recruitment Effectiveness Dashboard
6. Metrics Supported
| Metric | Supported Breakdowns |
| Recruitment Funnel | business_unit, source_category, location_country, job_function |
| Recruitment Funnel: Pass-Through Rate (%) | No drilldowns |
| Avg Time Spent in Stage Group + Match Stars | No drilldowns |
7. Known Exclusions / Filters Applied
- stage_mapping_dedup uses DISTINCT to remove duplicate stage mappings — multiple rows for the same (group_id, stage_group) combination are collapsed to one, preventing fan-out in the INNER JOIN to application_stage.
- The JOIN between application_stage and stage_mapping_dedup is an INNER JOIN — applications whose stage_group has no matching entry in stage_mapping are excluded from the dataset entirely.
- position_hire_flag flags any position_id that has at least one hired application (hired_ts IS NOT NULL) via a separate DISTINCT subquery, enabling is_hired_position without joining back to the full applications table.
- days_in_stage_group uses hired_ts (from applications) as the end timestamp for the Hired stage, and next_stage_ts (from the LEAD window) for all other stages — identified via LOWER(stage_group_display_name) LIKE '%hired%' OR LOWER(ef_stage_group) LIKE '%hired%'.
- is_calibrated = 1 when >= 4 of 5 position calibration flags are TRUE (has_calibrated_location, has_calibrated_skills, has_calibrated_titles, has_calibrated_similar_cand, has_calibrated_workexp). The match_stars column in Stage Time and Match Score only averages over calibrated positions.
- source_category is derived in application_hire_info via a priority-based CASE WHEN waterfall over source_type, source_name, and utm_source covering Internal Mobility, Referral, Recruiter, Career Site, Social Media, Job Boards (LinkedIn, Indeed, Google, Glassdoor, Naukri, Monster, Ziprecruiter, Seek, Built In), Eightfold alerts, and others.
- Date range filtering maps to positions.creation_ts via the override_filters date_range configuration.
- pass_through_rate in the Recruitment Funnel uses FIRST_VALUE(COUNT(DISTINCT application_id)) OVER (ORDER BY stage_group_index ASC) as the denominator — this anchors the denominator to stage_group_index = 1 (New Applications) for all stages.
8. Schema
| Column Name | Data Type | Notes |
| group_id | varchar | Customer/organization identifier; sourced from application_stage |
| position_id | bigint | Position associated with the application; sourced from application_stage |
| profile_id | bigint | Candidate's profile identifier; sourced from application_stage |
| application_id | varchar | Unique application identifier; sourced from application_stage. Primary COUNT DISTINCT grain for all funnel metrics. |
| stage | varchar | Raw stage name from the customer's ATS; sourced from application_stage |
| stage_ts | datetime | Timestamp when the application entered this stage; sourced from application_stage |
| stage_group | varchar | Standardized stage group name; sourced from stage_mapping (joined via group_id and stage) |
| stage_group_index | bigint | Numeric ordering of the stage group (1=New Applications, 2=Screening, 3=HM or 1st Interview, 4=Advanced Interviews, 5=Offers, 6=Offer Declined, 7=Hired); sourced from stage_mapping |
| ef_stage_group | varchar | Eightfold canonical stage group label; sourced from stage_mapping |
| stage_group_display_name | varchar | Display name for the stage group used in chart labels; sourced from stage_mapping |
| next_stage_ts | datetime | Derived (window): LEAD(stage_ts) OVER (PARTITION BY group_id, position_id, profile_id, application_id ORDER BY stage_ts). Timestamp of the next stage reached. |
| next_stage_group | varchar | Derived (window): LEAD(stage_group) — name of the next stage group reached. |
| next_stage_group_index | bigint | Derived (window): LEAD(stage_group_index) — numeric index of the next stage group. |
| days_in_stage_group | bigint | Derived: DATE_DIFF('DAY', next_stage_ts OR hired_ts, stage_ts). Uses hired_ts for the Hired stage, next_stage_ts for all others. Time the application spent in this stage before advancing. |
| match_stars | double | Candidate's Eightfold match score; sourced from applications. Only averaged in Stage Time metrics when is_calibrated = 1. |
| hired_ts | datetime | Hire timestamp; sourced from applications. Used as the end timestamp for days_in_stage_group on the Hired stage row. |
| application_ts | datetime | Application submission timestamp; sourced from applications |
| source_category | varchar | Derived: priority-based CASE WHEN waterfall over applications.source_type, source_name, and utm_source. Values include Internal Mobility, Referral, Recruiter (Chrome Extension), LinkedIn, Indeed, Google, Glassdoor, Career Site, Social Media, Eightfold, and others. |
| is_hired_application | bigint | Derived: 1 when hired_ts IS NOT NULL on the application; sourced from applications |
| is_hired_position | bigint | Derived: 1 when any application for this position_id has been hired (from position_hire_flag CTE). |
| is_calibrated | bigint | Derived: 1 when >= 4 of 5 calibration flags are TRUE on the position (has_calibrated_location, has_calibrated_skills, has_calibrated_titles, has_calibrated_similar_cand, has_calibrated_workexp); sourced from positions |
| is_open_position | bigint | Derived: 1 when positions.is_open = TRUE; sourced from positions |
| is_closed_position | bigint | Derived: 1 when positions.closed_at IS NOT NULL; sourced from positions |
| closed_at | datetime | Position close timestamp; sourced from positions |
| position_creation_ts | datetime | Position creation timestamp; sourced from positions. Primary date field for date range filtering. |
| recruiter | varchar | Recruiter owning the position; sourced from positions |
| job_function | varchar | Job function/category of the position; sourced from positions |
| location_country | varchar | Country of the position; sourced from positions |
| business_unit | varchar | Business unit of the position; sourced from positions |
| hiring_manager | varchar | Hiring manager for the position; sourced from positions |
| system_id | varchar | ATS system identifier for the application stage record; sourced from application_stage |