| """ |
| email-deliverability-scorer — LeadsBlue Hugging Face Space. |
| |
| Estimates an email list's expected deliverability (0-100) from honest, real |
| factors: verification claim, data age, country compliance friction, and |
| industry receptiveness (derived from benchmark open rates). |
| |
| This is an estimate, not a guarantee (stated in the UI). |
| |
| Data source: country-insights.json, industry-insights.json |
| Author: Luther Johnson (ORCID 0009-0008-9836-1280) · LeadsBlue Research |
| License: CC BY 4.0 · Dataset DOI: 10.5281/zenodo.20136256 |
| """ |
|
|
| import gradio as gr |
|
|
| from leadsblue_common import ( |
| CITATION_FOOTER, |
| softwareapplication_jsonld, |
| load_country_insights, |
| load_industry_insights, |
| parse_pct_range, |
| ) |
|
|
| try: |
| COUNTRIES = load_country_insights() |
| INDUSTRIES = load_industry_insights() |
| LOAD_ERROR = None |
| except Exception as exc: |
| COUNTRIES, INDUSTRIES, LOAD_ERROR = {}, {}, str(exc) |
|
|
| COUNTRY_CHOICES = sorted(c.title() for c in COUNTRIES.keys()) |
| INDUSTRY_CHOICES = sorted(INDUSTRIES.keys()) |
| VERIFICATION_CHOICES = ["Yes — recently verified", "Partial", "No / unknown"] |
| AGE_CHOICES = ["Under 6 months", "6–12 months", "12–24 months", "24+ months"] |
|
|
| |
| GDPR_COUNTRIES = { |
| "austria", "belgium", "bulgaria", "croatia", "cyprus", "czech republic", |
| "denmark", "estonia", "finland", "france", "germany", "greece", "hungary", |
| "ireland", "italy", "latvia", "lithuania", "luxembourg", "malta", |
| "netherlands", "poland", "portugal", "romania", "slovakia", "slovenia", |
| "spain", "sweden", "united kingdom", |
| } |
| CANSPAM_COUNTRIES = {"united states", "canada"} |
|
|
| VERIFICATION_POINTS = {"Yes — recently verified": 30, "Partial": 10, "No / unknown": 0} |
| AGE_POINTS = {"Under 6 months": 0, "6–12 months": -10, "12–24 months": -20, "24+ months": -35} |
|
|
|
|
| def _compliance_friction(country): |
| c = country.lower() |
| if c in GDPR_COUNTRIES: |
| return -10, "GDPR jurisdiction (consent expectations): -10" |
| if c in CANSPAM_COUNTRIES: |
| return -3, "CAN-SPAM/CASL jurisdiction: -3" |
| return 0, "Lighter regulatory friction: 0" |
|
|
|
|
| def _industry_receptiveness(industry): |
| perf = INDUSTRIES.get(industry, {}).get("cold_email_performance", {}) |
| if "open_rate" not in perf: |
| return 0, "Industry receptiveness: no data (0)" |
| lo, hi = parse_pct_range(perf["open_rate"]) |
| mid = (lo + hi) / 2 |
| if mid >= 25: |
| return 10, "High-receptiveness industry (open ~%.0f%%): +10" % mid |
| if mid >= 20: |
| return 6, "Above-average receptiveness (open ~%.0f%%): +6" % mid |
| if mid >= 15: |
| return 3, "Moderate receptiveness (open ~%.0f%%): +3" % mid |
| return 0, "Lower-receptiveness industry (open ~%.0f%%): 0" % mid |
|
|
|
|
| def score(country, industry, verification, data_age, list_source): |
| if LOAD_ERROR: |
| return "**Data failed to load.** %s" % LOAD_ERROR |
| if not country or not industry or not verification or not data_age: |
| return "Please complete country, industry, verification, and data age." |
|
|
| base = 50 |
| parts = ["Baseline: 50"] |
|
|
| v = VERIFICATION_POINTS[verification] |
| parts.append("Verification (%s): %+d" % (verification, v)) |
|
|
| a = AGE_POINTS[data_age] |
| parts.append("Data age (%s): %+d" % (data_age, a)) |
|
|
| cf, cf_note = _compliance_friction(country) |
| parts.append(cf_note) |
|
|
| ir, ir_note = _industry_receptiveness(industry) |
| parts.append(ir_note) |
|
|
| total = max(0, min(100, base + v + a + cf + ir)) |
|
|
| if total >= 75: |
| verdict = "Strong — list profile supports good deliverability." |
| elif total >= 55: |
| verdict = "Moderate — workable with verification and warm-up." |
| elif total >= 35: |
| verdict = "Caution — refresh and re-verify before sending at volume." |
| else: |
| verdict = "High risk — re-source or heavily clean before use." |
|
|
| recs = [] |
| if v < 30: |
| recs.append("Verify the list with a real-time validation pass before sending.") |
| if a < 0: |
| recs.append("Refresh records older than 6 months; B2B data decays ~2-3%/month.") |
| if cf < 0: |
| recs.append("For this jurisdiction, ensure a legitimate-interest basis and easy opt-out.") |
| if not recs: |
| recs.append("Maintain list hygiene and monitor bounce/complaint rates per send.") |
|
|
| body = ( |
| "## Deliverability estimate: %d / 100\n\n" |
| "**%s**\n\n" |
| "### Score breakdown\n%s\n\n" |
| "### Recommended actions\n%s\n\n" |
| "> _This is an estimate based on benchmark factors, not a guarantee. " |
| "Actual deliverability depends on sender reputation, content, and ESP " |
| "configuration._\n\n---\n%s" |
| ) % ( |
| total, |
| verdict, |
| "\n".join("- " + p for p in parts), |
| "\n".join("- " + r for r in recs), |
| CITATION_FOOTER, |
| ) |
| return body |
|
|
|
|
| HEAD = softwareapplication_jsonld( |
| "LeadsBlue Email Deliverability Scorer", |
| "Estimates B2B email list deliverability from verification, data age, jurisdiction, and industry.", |
| ) |
|
|
| _blocks_kwargs = {"title": "LeadsBlue Email Deliverability Scorer"} |
| try: |
| demo = gr.Blocks(head=HEAD, **_blocks_kwargs) |
| except TypeError: |
| demo = gr.Blocks(**_blocks_kwargs) |
| with demo: |
| gr.Markdown( |
| "# LeadsBlue Email Deliverability Scorer\n" |
| "An honest, factor-based estimate of how a B2B list is likely to perform. " |
| "No guarantees — just transparent scoring." |
| ) |
| with gr.Row(): |
| country = gr.Dropdown(COUNTRY_CHOICES, label="Country", value=("United States" if "United States" in COUNTRY_CHOICES else None)) |
| industry = gr.Dropdown(INDUSTRY_CHOICES, label="Industry", value=(INDUSTRY_CHOICES[0] if INDUSTRY_CHOICES else None)) |
| with gr.Row(): |
| verification = gr.Dropdown(VERIFICATION_CHOICES, label="Email verification", value="Partial") |
| data_age = gr.Dropdown(AGE_CHOICES, label="Data age", value="6–12 months") |
| list_source = gr.Textbox(label="List source (optional)", placeholder="e.g. opt-in webinar, scraped directory, purchased...") |
| btn = gr.Button("Score deliverability", variant="primary") |
| out = gr.Markdown() |
| btn.click(score, [country, industry, verification, data_age, list_source], out) |
| gr.Markdown("---\n_%s_" % CITATION_FOOTER) |
|
|
| if __name__ == "__main__": |
| try: |
| demo.launch(head=HEAD) |
| except TypeError: |
| demo.launch() |
|
|