Skip to content

Funnel Quality by Intake Source

A comparison of funnel quality — application rate and engagement depth — grouped by how each person first entered Slate. Intake source is derived from the person’s earliest Slate source record, classified into intake categories from the source name and summary. It separates cold-acquired names (recruitment fairs, purchased lists) from inbound and engaged sources.

Not all funnel volume is equal, and the intake source shows exactly where the low-quality volume comes from. Cold-acquired name lists — recruitment fairs, purchased vendor leads, and bulk spreadsheet uploads — convert at 0.5%–7.6% and are mostly inert. Inbound and nurtured sources convert far higher.

Cold acquisition sources (recruitment-controllable)

Intake SourcePersonsApplication RateAvg Engagement Touches% Ever Engaged
recruitment fair / webinar51,6640.5%1.911.6%
purchased lead vendor5,6931.5%4.113.1%
spreadsheet upload (other)59,0727.6%16.017.0%
web / form5,88611.0%49.9100.0%
EDDY12,25223.0%72.683.4%

Administrative / applicant-stage imports (not recruitment sources — see caveat)

Intake SourcePersonsApplication RateAvg Engagement Touches% Ever Engaged
internal / SIS load (Banner)7,28099.6%188.688.6%
application service (CAS)1,40887.2%46.265.4%
test score import2,85251.6%129.554.1%
data maintenance8,37938.5%84.196.3%
other / unclassified27,87551.8%39.230.7%

Among the sources a recruitment budget actually controls, there is a stark quality gradient. Recruitment fairs and purchased vendor lists are near-inert — 0.5% and 1.5% application rates, with fewer than 14% of names ever generating a single engagement touch. These are the bulk-volume, low-yield sources. At the other end, EDDY converts at 23% with 83% of its leads engaging — a genuinely productive source, distinct from the in-platform and list-buy populations it is sometimes lumped with.

This is the evidence base for reallocation: the institution is acquiring tens of thousands of names through recruitment fairs and vendor lists that almost never convert, while its engaged and inbound sources — the ones that actually produce applicants — are a fraction of the volume. The FY2025 funnel weakness was driven almost entirely by one cold source: a single EducationUSA virtual-fair name list of ~23,600 records.

Blended funnel metrics hide this. A 0.5% recruitment-fair name and a 23% EDDY lead both count as one person in the funnel, but they represent completely different value. Grouping by intake source lets leadership see where acquisition spend produces applicants and where it produces inert records that only depress the blended application rate.

For board-level budget conversations, this table answers directly: which acquisition sources are worth the money? Recruitment fairs and purchased lists deliver volume without conversion. EDDY and inbound web deliver conversion. That is a defensible basis for shifting dollars.

Each person is assigned an origin source — the earliest Slate source record by sources.created_at. That source’s format name (source_formats.name) or free-text summary (sources.summary) is classified into an intake group via a CASE statement.

WITH person_origin AS (
SELECT person_id, intake_group FROM (
SELECT
sr.record_id AS person_id,
CASE
WHEN lower(COALESCE(sf.name, s.summary)) LIKE '%virtual fair%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%webinar%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%educationusa%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%isn %'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%grad fair%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%registrant%'
THEN 'recruitment fair / webinar'
WHEN lower(COALESCE(sf.name, s.summary)) LIKE '%eddy%'
THEN 'EDDY'
WHEN lower(COALESCE(sf.name, s.summary)) LIKE '%niche%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%carnegie%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%peterson%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%qs %'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%u.s. news%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%student connect%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%cappex%'
THEN 'purchased lead vendor'
WHEN lower(COALESCE(sf.name, s.summary)) LIKE '%ielts%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%toefl%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%gre %'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%duolingo%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%score%'
THEN 'test score import'
WHEN lower(COALESCE(sf.name, s.summary)) LIKE '%cas %'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%caspa%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%atcas%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%dicas%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%nursingcas%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%liaison%'
THEN 'application service (CAS)'
WHEN lower(COALESCE(sf.name, s.summary)) LIKE '%banner%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%slate%'
THEN 'internal / SIS load'
WHEN lower(COALESCE(sf.name, s.summary)) LIKE '%correction%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%audit%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%missing%'
THEN 'data maintenance'
WHEN lower(COALESCE(sf.name, s.summary)) LIKE '%.csv%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%.xlsx%'
THEN 'spreadsheet upload (other)'
WHEN lower(COALESCE(sf.name, s.summary)) LIKE '%web service post%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%form%'
OR lower(COALESCE(sf.name, s.summary)) LIKE '%http%'
THEN 'web / form'
ELSE 'other / unclassified'
END AS intake_group,
ROW_NUMBER() OVER (
PARTITION BY sr.record_id
ORDER BY s.created_at ASC
) AS rn
FROM source_records sr
JOIN sources s ON sr.source_id = s.id
LEFT JOIN source_formats sf ON s.format_id = sf.id
JOIN persons p ON sr.record_id = p.id
) WHERE rn = 1
),
eng AS (
SELECT person_id, COUNT(*) FILTER (WHERE touch_category = 'engagement') AS engagement_touches
FROM person_touches
GROUP BY person_id
)
SELECT
po.intake_group,
COUNT(*) AS persons,
ROUND(SUM(CASE WHEN pd.applied = 'Yes' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS application_rate,
ROUND(AVG(COALESCE(eng.engagement_touches, 0)), 1) AS avg_engagement_touches,
ROUND(COUNT(*) FILTER (WHERE COALESCE(eng.engagement_touches, 0) > 0) * 100.0 / COUNT(*), 1) AS pct_ever_engaged
FROM person_origin po
JOIN persons_dashboard pd ON po.person_id = pd.person_id
LEFT JOIN eng ON po.person_id = eng.person_id
GROUP BY 1
ORDER BY persons DESC;