Marketing Qualified Leads (MQL)
Leads that have met specific qualification criteria and are ready for sales engagement
Overview
Marketing Qualified Leads (MQLs) are prospects who have demonstrated sufficient interest and fit specific criteria that indicate they're ready for sales engagement. MQLs bridge the gap between marketing-generated leads and sales-ready opportunities.
MQL qualification typically combines demographic fit (job title, company size, industry), behavioral signals (content downloads, website activity), engagement levels (email interactions, event attendance), and buying intent indicators to identify leads most likely to convert.
MQL Rate = (Number of MQLs / Total Leads Generated) × 100
Demographic Fit
Job title, company size, industry match
Ideal customer profileBehavioral Signals
Content downloads, page views, time on site
Engagement depthEngagement Level
Email opens, clicks, responses
Communication interestBuying Intent
Pricing views, demo requests, trials
Purchase readinessVisitor
Website traffic
Lead
Contact captured
MQL
Qualified by marketing
SQL
Accepted by sales
Customer
Closed won
Qualification Alignment
MQL criteria should be jointly defined by marketing and sales teams to ensure leads passed to sales are truly ready for engagement and have high conversion potential.
Why It Matters
- Sales Efficiency: Improves sales productivity by focusing on qualified prospects
- Marketing ROI: Demonstrates marketing's contribution to revenue pipeline
- Process Optimization: Identifies areas for lead nurturing improvement
- Revenue Predictability: Enables better forecasting and planning
- Team Alignment: Creates clear handoff criteria between marketing and sales
- Resource Allocation: Guides investment in high-performing channels
How to Measure It
Calculate MQL metrics by analyzing lead qualification criteria, conversion rates, and progression through the sales funnel across different channels and campaigns.
Basic MQL Calculation
-- Calculate Marketing Qualified Lead metrics and conversion rates
WITH lead_scoring AS (
SELECT
l.lead_id,
l.email,
l.created_date,
l.source,
l.campaign_id,
l.lead_status,
-- Demographic scoring
CASE
WHEN le.job_title IN ('CEO', 'CTO', 'VP', 'Director', 'Manager') THEN 20
WHEN le.job_title IN ('Senior', 'Lead', 'Principal') THEN 15
WHEN le.job_title IN ('Analyst', 'Specialist', 'Coordinator') THEN 10
ELSE 5
END as demographic_score,
-- Firmographic scoring
CASE
WHEN le.company_size >= 1000 THEN 25
WHEN le.company_size >= 100 THEN 20
WHEN le.company_size >= 50 THEN 15
WHEN le.company_size >= 10 THEN 10
ELSE 5
END as firmographic_score,
-- Industry fit scoring
CASE
WHEN le.industry IN ('Technology', 'Financial Services', 'Healthcare') THEN 15
WHEN le.industry IN ('Manufacturing', 'Retail', 'Education') THEN 10
ELSE 5
END as industry_score,
le.job_title,
le.company_size,
le.industry,
DATE_TRUNC('month', l.created_date) as lead_month
FROM leads l
LEFT JOIN lead_enrichment le ON l.lead_id = le.lead_id
WHERE l.created_date >= CURRENT_DATE - INTERVAL '12 months'
),
behavioral_scoring AS (
SELECT
wa.lead_id,
COUNT(DISTINCT wa.page_url) as pages_visited,
COUNT(*) as total_page_views,
SUM(wa.time_on_page_seconds) as total_time_on_site,
COUNT(DISTINCT CASE WHEN wa.page_type = 'pricing' THEN wa.page_url END) as pricing_pages,
COUNT(DISTINCT CASE WHEN wa.page_type = 'demo' THEN wa.page_url END) as demo_pages,
COUNT(DISTINCT CASE WHEN wa.page_type = 'case_study' THEN wa.page_url END) as case_studies,
-- Behavioral score calculation
LEAST(20, COUNT(DISTINCT wa.page_url) * 2) + -- Max 20 points for page diversity
LEAST(15, COUNT(DISTINCT CASE WHEN wa.page_type = 'pricing' THEN wa.page_url END) * 10) + -- Pricing intent
LEAST(20, COUNT(DISTINCT CASE WHEN wa.page_type = 'demo' THEN wa.page_url END) * 20) + -- Demo intent
LEAST(10, SUM(wa.time_on_page_seconds) / 60) as behavioral_score -- Time engagement
FROM website_activity wa
WHERE wa.activity_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY wa.lead_id
),
engagement_scoring AS (
SELECT
la.lead_id,
COUNT(CASE WHEN la.activity_type = 'email_open' THEN 1 END) as email_opens,
COUNT(CASE WHEN la.activity_type = 'email_click' THEN 1 END) as email_clicks,
COUNT(CASE WHEN la.activity_type = 'form_submission' THEN 1 END) as form_submissions,
COUNT(CASE WHEN la.activity_type = 'content_download' THEN 1 END) as content_downloads,
COUNT(CASE WHEN la.activity_type = 'webinar_attendance' THEN 1 END) as webinar_attendance,
-- Engagement score calculation
LEAST(15, COUNT(CASE WHEN la.activity_type = 'email_click' THEN 1 END) * 3) +
LEAST(20, COUNT(CASE WHEN la.activity_type = 'form_submission' THEN 1 END) * 10) +
LEAST(15, COUNT(CASE WHEN la.activity_type = 'content_download' THEN 1 END) * 5) +
LEAST(25, COUNT(CASE WHEN la.activity_type = 'webinar_attendance' THEN 1 END) * 25) as engagement_score
FROM lead_activities la
WHERE la.activity_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY la.lead_id
),
mql_qualification AS (
SELECT
ls.lead_id,
ls.email,
ls.created_date,
ls.source,
ls.campaign_id,
ls.lead_status,
ls.lead_month,
ls.demographic_score,
ls.firmographic_score,
ls.industry_score,
COALESCE(bs.behavioral_score, 0) as behavioral_score,
COALESCE(es.engagement_score, 0) as engagement_score,
ls.demographic_score + ls.firmographic_score + ls.industry_score +
COALESCE(bs.behavioral_score, 0) + COALESCE(es.engagement_score, 0) as total_score,
-- MQL qualification criteria
CASE
WHEN (ls.demographic_score + ls.firmographic_score + ls.industry_score +
COALESCE(bs.behavioral_score, 0) + COALESCE(es.engagement_score, 0)) >= 70 THEN 1
ELSE 0
END as is_mql,
bs.pages_visited,
bs.pricing_pages,
bs.demo_pages,
es.email_clicks,
es.form_submissions,
es.content_downloads
FROM lead_scoring ls
LEFT JOIN behavioral_scoring bs ON ls.lead_id = bs.lead_id
LEFT JOIN engagement_scoring es ON ls.lead_id = es.lead_id
),
mql_metrics AS (
SELECT
source,
lead_month,
COUNT(*) as total_leads,
SUM(is_mql) as mql_count,
ROUND(100.0 * SUM(is_mql) / COUNT(*), 1) as mql_rate,
ROUND(AVG(total_score), 1) as avg_lead_score,
ROUND(AVG(CASE WHEN is_mql = 1 THEN total_score END), 1) as avg_mql_score,
-- Score component analysis
ROUND(AVG(demographic_score), 1) as avg_demographic_score,
ROUND(AVG(firmographic_score), 1) as avg_firmographic_score,
ROUND(AVG(behavioral_score), 1) as avg_behavioral_score,
ROUND(AVG(engagement_score), 1) as avg_engagement_score
FROM mql_qualification
GROUP BY source, lead_month
)
SELECT
source,
lead_month,
total_leads,
mql_count,
mql_rate,
avg_lead_score,
avg_mql_score,
avg_demographic_score,
avg_firmographic_score,
avg_behavioral_score,
avg_engagement_score,
LAG(mql_rate) OVER (PARTITION BY source ORDER BY lead_month) as prev_month_mql_rate,
ROUND(mql_rate - LAG(mql_rate) OVER (PARTITION BY source ORDER BY lead_month), 1) as mql_rate_change,
RANK() OVER (PARTITION BY lead_month ORDER BY mql_rate DESC) as source_rank
FROM mql_metrics
WHERE total_leads >= 10 -- Minimum sample size
ORDER BY lead_month DESC, mql_rate DESC;
MQL Conversion Analysis
-- Analyze MQL to SQL and customer conversion rates
WITH mql_progression AS (
SELECT
mq.lead_id,
mq.email,
mq.created_date,
mq.source,
mq.total_score,
mq.is_mql,
-- Sales qualification
CASE
WHEN o.opportunity_id IS NOT NULL THEN 1
ELSE 0
END as became_sql,
o.created_date as sql_date,
EXTRACT(days FROM AGE(o.created_date, mq.created_date)) as days_to_sql,
-- Customer conversion
CASE
WHEN o.stage = 'Closed Won' THEN 1
ELSE 0
END as became_customer,
o.close_date as customer_date,
o.amount as deal_value,
EXTRACT(days FROM AGE(o.close_date, mq.created_date)) as days_to_customer
FROM mql_qualification mq
LEFT JOIN opportunities o ON mq.lead_id = o.lead_id
WHERE mq.is_mql = 1 -- Focus on MQLs only
),
conversion_funnel AS (
SELECT
source,
DATE_TRUNC('month', created_date) as mql_month,
COUNT(*) as total_mqls,
SUM(became_sql) as sql_conversions,
SUM(became_customer) as customer_conversions,
ROUND(100.0 * SUM(became_sql) / COUNT(*), 1) as mql_to_sql_rate,
ROUND(100.0 * SUM(became_customer) / COUNT(*), 1) as mql_to_customer_rate,
ROUND(100.0 * SUM(became_customer) / NULLIF(SUM(became_sql), 0), 1) as sql_to_customer_rate,
ROUND(AVG(days_to_sql), 1) as avg_days_to_sql,
ROUND(AVG(days_to_customer), 1) as avg_days_to_customer,
ROUND(AVG(deal_value), 0) as avg_deal_value,
SUM(deal_value) as total_revenue
FROM mql_progression
GROUP BY source, DATE_TRUNC('month', created_date)
),
cohort_analysis AS (
SELECT
mp.source,
DATE_TRUNC('month', mp.created_date) as cohort_month,
COUNT(*) as cohort_size,
-- Month 1 conversions
SUM(CASE WHEN mp.sql_date <= mp.created_date + INTERVAL '30 days' THEN 1 ELSE 0 END) as month_1_sql,
SUM(CASE WHEN mp.customer_date <= mp.created_date + INTERVAL '30 days' THEN 1 ELSE 0 END) as month_1_customers,
-- Month 3 conversions
SUM(CASE WHEN mp.sql_date <= mp.created_date + INTERVAL '90 days' THEN 1 ELSE 0 END) as month_3_sql,
SUM(CASE WHEN mp.customer_date <= mp.created_date + INTERVAL '90 days' THEN 1 ELSE 0 END) as month_3_customers,
-- Month 6 conversions
SUM(CASE WHEN mp.sql_date <= mp.created_date + INTERVAL '180 days' THEN 1 ELSE 0 END) as month_6_sql,
SUM(CASE WHEN mp.customer_date <= mp.created_date + INTERVAL '180 days' THEN 1 ELSE 0 END) as month_6_customers
FROM mql_progression mp
WHERE mp.created_date >= CURRENT_DATE - INTERVAL '12 months'
GROUP BY source, DATE_TRUNC('month', mp.created_date)
HAVING COUNT(*) >= 10 -- Minimum cohort size
)
SELECT
source,
cohort_month,
cohort_size,
month_1_sql,
month_3_sql,
month_6_sql,
month_1_customers,
month_3_customers,
month_6_customers,
ROUND(100.0 * month_1_sql / cohort_size, 1) as month_1_sql_rate,
ROUND(100.0 * month_3_sql / cohort_size, 1) as month_3_sql_rate,
ROUND(100.0 * month_6_sql / cohort_size, 1) as month_6_sql_rate,
ROUND(100.0 * month_1_customers / cohort_size, 1) as month_1_customer_rate,
ROUND(100.0 * month_3_customers / cohort_size, 1) as month_3_customer_rate,
ROUND(100.0 * month_6_customers / cohort_size, 1) as month_6_customer_rate
FROM cohort_analysis
ORDER BY cohort_month DESC, month_6_customer_rate DESC;
MQL Quality Analysis
-- Analyze MQL quality by scoring components and characteristics
WITH mql_quality_analysis AS (
SELECT
mq.source,
mq.lead_month,
-- Score component ranges
CASE
WHEN mq.demographic_score >= 20 THEN 'High Demographic Fit'
WHEN mq.demographic_score >= 15 THEN 'Medium Demographic Fit'
ELSE 'Low Demographic Fit'
END as demographic_tier,
CASE
WHEN mq.behavioral_score >= 30 THEN 'High Engagement'
WHEN mq.behavioral_score >= 15 THEN 'Medium Engagement'
ELSE 'Low Engagement'
END as behavioral_tier,
CASE
WHEN mq.engagement_score >= 25 THEN 'High Intent'
WHEN mq.engagement_score >= 15 THEN 'Medium Intent'
ELSE 'Low Intent'
END as intent_tier,
mq.total_score,
mp.became_sql,
mp.became_customer,
mp.deal_value,
mp.days_to_sql,
mp.days_to_customer
FROM mql_qualification mq
LEFT JOIN mql_progression mp ON mq.lead_id = mp.lead_id
WHERE mq.is_mql = 1
),
quality_metrics AS (
SELECT
demographic_tier,
behavioral_tier,
intent_tier,
COUNT(*) as mql_count,
ROUND(100.0 * SUM(became_sql) / COUNT(*), 1) as sql_conversion_rate,
ROUND(100.0 * SUM(became_customer) / COUNT(*), 1) as customer_conversion_rate,
ROUND(AVG(days_to_sql), 1) as avg_days_to_sql,
ROUND(AVG(days_to_customer), 1) as avg_days_to_customer,
ROUND(AVG(deal_value), 0) as avg_deal_value,
ROUND(SUM(deal_value) / COUNT(*), 0) as revenue_per_mql
FROM mql_quality_analysis
GROUP BY demographic_tier, behavioral_tier, intent_tier
HAVING COUNT(*) >= 5 -- Minimum sample size
),
source_performance AS (
SELECT
source,
COUNT(*) as total_mqls,
ROUND(100.0 * SUM(became_sql) / COUNT(*), 1) as sql_conversion_rate,
ROUND(100.0 * SUM(became_customer) / COUNT(*), 1) as customer_conversion_rate,
ROUND(AVG(total_score), 1) as avg_mql_score,
ROUND(AVG(CASE WHEN became_customer = 1 THEN total_score END), 1) as avg_converting_score,
ROUND(AVG(deal_value), 0) as avg_deal_value,
ROUND(SUM(deal_value) / COUNT(*), 0) as revenue_per_mql,
SUM(deal_value) as total_revenue
FROM mql_quality_analysis
GROUP BY source
HAVING COUNT(*) >= 20 -- Minimum sample size
),
scoring_effectiveness AS (
SELECT
CASE
WHEN total_score >= 90 THEN '90-100'
WHEN total_score >= 80 THEN '80-89'
WHEN total_score >= 70 THEN '70-79'
ELSE '60-69'
END as score_range,
COUNT(*) as mql_count,
ROUND(100.0 * SUM(became_sql) / COUNT(*), 1) as sql_rate,
ROUND(100.0 * SUM(became_customer) / COUNT(*), 1) as customer_rate,
ROUND(AVG(deal_value), 0) as avg_deal_value
FROM mql_quality_analysis
WHERE total_score >= 60 -- MQL threshold
GROUP BY 1
ORDER BY MIN(total_score) DESC
)
SELECT
score_range,
mql_count,
sql_rate,
customer_rate,
avg_deal_value,
RANK() OVER (ORDER BY customer_rate DESC) as performance_rank
FROM scoring_effectiveness
UNION ALL
SELECT
CONCAT('Source: ', source) as score_range,
total_mqls as mql_count,
sql_conversion_rate as sql_rate,
customer_conversion_rate as customer_rate,
avg_deal_value,
RANK() OVER (ORDER BY customer_conversion_rate DESC) as performance_rank
FROM source_performance
ORDER BY performance_rank;
Scoring Best Practices
Regularly validate MQL criteria against conversion outcomes, use negative scoring for disqualifying factors, implement time decay for behavioral signals, and adjust thresholds based on sales feedback.
Best Practices
1. Qualification Criteria
- Define clear, measurable qualification criteria
- Include both demographic and behavioral signals
- Weight factors based on conversion correlation
- Use negative scoring for disqualifying characteristics
2. Sales-Marketing Alignment
- Collaborate on MQL definition and criteria
- Establish clear SLA for follow-up timing
- Create feedback loop for MQL quality assessment
- Regularly review and adjust qualification thresholds
3. Scoring Optimization
- Data-Driven Weights: Base on historical conversion rates
- Time Decay: Reduce score for old behavioral signals
- Dynamic Scoring: Adjust based on lead source and campaign
- Regular Calibration: Update criteria quarterly
4. Measurement & Analysis
- Track MQL volume, quality, and conversion rates
- Analyze by source, campaign, and time period
- Monitor velocity from MQL to SQL to customer
- Calculate revenue attribution and ROI by source
5. Process Improvement
- Implement lead nurturing for not-yet-qualified leads
- Create automated workflows for MQL processing
- Provide sales context and lead history
- Track and optimize handoff processes