Score Company Websites Against Your ICP with Jev
GuideCreate a company scoring workflow using public website evidence, an explicit ICP rubric, Jev decisions, and human review for incomplete records.
Jev lead scoring rates how well a company fits your ideal customer profile (ICP), using facts from its public website. MrScraper collects the company's description, products, and quoted evidence. Jev scores each ICP dimension separately. Your code combines the scores with your own weights and sends unclear companies to a person.
TL;DR
- Score fit, not intent. A website shows what a company does. It does not show whether it is ready to buy.
- One question per dimension. Score industry, offering, and market separately, then weight them in code.
- Unknown is not zero. Missing evidence sends a company to review instead of the bottom of the list. Most account lists are long, and most of the useful facts sit on company websites. Reading every "About" page by hand does not scale. This guide shows how to turn public website evidence into a ranked, reviewable account list. It is a custom workflow, and every number it produces should be checked against your own labeled examples.
New to Jev? Read What Is Jev? first. For the Python basics used below, see Classify Web Data with Jev and MrScraper.
How can Jev support company website lead scoring?
Jev can rate each company against a rubric you write, using only the evidence you extracted from its website. It returns a position on each scale plus a confidence value. That gives your team a consistent first pass, with every score tied to a quote and a source URL.
Score company fit using visible evidence
TypeSafe lists matching company profiles to an ideal customer profile as an example use case in its use case map. This guide turns that idea into a concrete, testable workflow.
The key word is visible. A good website fit signal is something a reviewer can point to on the page:
- "We sell handmade furniture online and ship across Europe." This is a visible fact.
- "They are probably growing fast." This is an inference, and it does not belong in a fit score. Keeping to visible facts has two benefits. Reviewers can check every score in seconds. And the model is less likely to be pulled around by marketing language. TypeSafe's Jev 1.13 notes warn that text written to argue for its own classification can move the answer. Short, factual quotes are harder to oversell than a whole homepage.
How do you define an ICP rubric?
Write down each part of your ICP as its own dimension, with plain-language levels that describe real situations. Keep industry, offering and market separate. Add hard disqualifiers, like being a competitor, as yes/no checks that your code applies as a gate.
Separate industry, offering and market criteria
Here is an example rubric. It is author-created for a fictional company that sells returns-management software to online stores. Swap in your own ICP.
| Dimension | Jev question type | Levels or condition | Weight |
|---|---|---|---|
| Industry | Score (4 levels) | 0: Not retail or e-commerce · 1: Retail, mostly in physical stores · 2: Sells online, mixed with other channels · 3: Online-first retailer | 0.40 |
| Offering | Score (3 levels) | 0: Sells services or digital goods only · 1: Sells some physical products · 2: Physical products are the core business | 0.35 |
| Market | Score (3 levels) | 0: Sells only to businesses · 1: Sells to both businesses and consumers · 2: Sells mainly to consumers | 0.25 |
| Competitor | Noul (gate) | "The company sells returns-management or reverse-logistics software." | Exclude if yes |
Some rules for writing a rubric that works:
- Describe situations, not degrees. "Online-first retailer" gives Jev something to match. "High fit" does not. TypeSafe's Score docs make the same point.
- One idea per dimension. A level like "online, consumer-focused and international" mixes three things. Split it.
- Keep numbers in code. Jev 1.13 is weak at math and counting, according to TypeSafe. If size matters, extract a stated figure and compare it in code, or leave size out.
- Use 2 to 10 levels. That is the range the Score type accepts. Three or four clear levels usually beat ten fuzzy ones.
Which website facts should MrScraper collect?
Collect a short company description, the main products or services, who the company sells to, and verbatim quotes that support each point. Store the page URL with every quote. Collect public company facts only, not personal contact data.
Company descriptions, products and cited source passages
For each company, the homepage and "About" page usually hold most of the evidence. A shipping or FAQ page often shows whether a company sells online and to whom. MrScraper's Map agent can list a site's URLs so you can pick those pages, and the General agent can extract fields from each one.
| Field | Typical page | Example value | Feeds |
|---|---|---|---|
company_name |
Homepage | "Oak & Ash Studio" | Record ID |
description |
About page | One or two sentences about the business | Industry, Offering |
products_or_services |
Homepage, shop | List of main product lines | Offering |
customer_types |
About, FAQ | "home owners", "interior designers" | Market |
sales_channels |
Homepage, FAQ | "online shop", "showroom" | Industry |
evidence_quotes |
Any page | Exact sentences copied from the page | Review and audit |
source_url |
Your code | The page each value came from | Review and audit |
An extraction prompt for the General agent can ask for these directly:
Extract as JSON:
- company_name (string)
- description (one or two sentences, copied from the page where possible)
- products_or_services (list of strings)
- customer_types (list of strings, only if stated on the page)
- sales_channels (list of strings, only if stated on the page)
- evidence_quotes (list of exact sentences copied from the page that support the fields above)
Use null for anything not stated on the page. Do not guess.
The last line matters most. "Use null" keeps unknowns visible, so your code can tell the difference between "this company sells to businesses" and "the page does not say."
How do you turn evidence into Jev questions?
Ask one Score question per ICP dimension and one Noul per disqualifier, all in a single request. Next to each Score, ask a Noul that checks whether the evidence covers that dimension at all. Then normalize the scores and combine them with your weights in code.
Score each dimension; combine weights in code
This follows TypeSafe's composite scoring pattern: break a judgment into separate scores, normalize each to 0 to 1, and weight them in code.
from typesafe_sdk import Noul, Score, TypeSafeClient
DIMENSIONS = {
"industry": (0.40, Score(
instructions="Which best describes the business in `evidence`?",
criteria=[
"Not a retail or e-commerce business",
"A retailer that sells mostly in physical stores",
"Sells online, alongside other sales channels",
"An online-first retailer",
],
)),
"offering": (0.35, Score(
instructions="What does the company in `evidence` mainly sell?",
criteria=[
"Services or digital goods only",
"Some physical products alongside services",
"Physical products are the core business",
],
)),
"market": (0.25, Score(
instructions="Who does the company in `evidence` sell to?",
criteria=[
"Only to other businesses",
"To both businesses and consumers",
"Mainly to consumers",
],
)),
}
COVERAGE = {
"industry": "Does `evidence` say how or where the company sells?",
"offering": "Does `evidence` say what the company sells?",
"market": "Does `evidence` say who the company's customers are?",
}
COMPETITOR = Noul(
instructions="Does the company in `evidence` sell returns-management or reverse-logistics software?"
)
def build_questions() -> dict:
questions = {name: q for name, (_, q) in DIMENSIONS.items()}
questions.update({f"{name}_covered": Noul(instructions=text) for name, text in COVERAGE.items()})
questions["is_competitor"] = COMPETITOR
return questions
def score_company(client: TypeSafeClient, company: dict) -> dict:
state = {
"evidence": {
"description": company["description"],
"products_or_services": company["products_or_services"],
"customer_types": company["customer_types"],
"sales_channels": company["sales_channels"],
"quotes": company["evidence_quotes"],
}
}
answers = client.system_one(state=state, questions=build_questions()).answers
dims = {}
for name, (weight, question) in DIMENSIONS.items():
top = len(question.criteria) - 1
dims[name] = {
"score": answers[name].score / top, # normalized 0 to 1
"confidence": answers[name].confidence,
"covered": answers[f"{name}_covered"].noul,
"weight": weight,
}
fit = sum(d["weight"] * d["score"] for d in dims.values())
return {"fit": round(fit, 3), "dims": dims, "competitor": answers["is_competitor"].noul}
Why this shape works:
- Every question sees the same evidence. TypeSafe evaluates the questions in parallel and in isolation, so one answer never leaks into another.
- Coverage questions catch gaps. A low market score could mean "sells to businesses" or "the page never says." The
_coveredNoul tells them apart. - Weights live in code. When the ranking disagrees with your team, change a number and rerun. You do not need to rewrite a prompt.
How do you handle unknown or ambiguous companies?
Route them to a person instead of forcing a score. A company with missing evidence on a heavy dimension, a split competitor check or low confidence should land in a review queue. Only clear, well-covered companies get an automatic tier.
Missing evidence and human review
Turn the answers into a decision with explicit rules:
YES, NO = 0.8, 0.2
MIN_CONFIDENCE = 0.5 # starting point; tune on labeled examples
def decide(result: dict) -> str:
if result["competitor"] >= YES:
return "exclude: competitor"
if NO < result["competitor"] < YES:
return "review: possible competitor"
for name, d in result["dims"].items():
if d["covered"] < NO and d["weight"] >= 0.3:
return f"review: no evidence for {name}"
if d["covered"] >= NO and d["confidence"] < MIN_CONFIDENCE:
return f"review: unclear {name}"
if result["fit"] >= 0.75:
return "tier A"
if result["fit"] >= 0.5:
return "tier B"
return "tier C"
| Situation | Rule | Outcome |
|---|---|---|
| Clearly a competitor | is_competitor at or above 0.8 |
Exclude |
| Maybe a competitor | is_competitor between 0.2 and 0.8 |
Review |
| Heavy dimension not covered | _covered below 0.2, weight 0.3 or more |
Review |
| Dimension covered but split | Confidence below 0.5 | Review |
| Everything clear | Use the fit score | Tier A, B or C |
These thresholds are starting points, not recommendations. TypeSafe's Confidence docs say the right values depend on your domain and should be tuned on your own data.
Make review fast. Show the reviewer the company name, each dimension score, the evidence quotes, and the source URLs on one screen. Store their decision as a label. Those labels become your next test set.
How do you evaluate account-scoring quality?
Compare Jev's ranking with fit decisions your team has already made. Label a small set of companies by hand, score them with the workflow, and check whether the top of the list matches your best-fit accounts. Fix the rubric where they disagree.
Compare rankings with labeled fit decisions
A practical first test, offered as a proposal rather than a benchmark:
- Pick 20 to 30 companies. Include clear fits, clear non-fits, a competitor or two, and a few hard cases. This small set is a starting check, not proof of accuracy.
- Label them blind. Have someone on your team mark each as a good fit, maybe, or poor fit, without seeing the scores.
- Run the workflow with a pinned model version, such as
jev-1.13.0. - Compare. How many of the top 10 by fit score did your team label "good fit"? How many "poor fit" companies landed in tier A? How many went to review?
- Read every disagreement. Look at the quotes. Often the rubric level was vague, or the extraction missed a key page. Record the results in an evidence-linked table so anyone can audit a score:
| Company | Industry | Offering | Market | Fit | Key evidence (quote) | Source URL | Team label | Agree? |
|---|---|---|---|---|---|---|---|---|
| Example Co A | 0.67 | 1.00 | 1.00 | 0.87 | "We design and sell furniture online..." | example-a.com/about | Good fit | Yes |
| Example Co B | 1.00 | 0.00 | 0.50 | 0.53 | "Our agency builds Shopify stores..." | example-b.com | Poor fit | No |
In the second example row, a web agency scored high on industry because it works with online stores. That is the kind of miss this table helps you catch. The fix is to sharpen the industry levels so they describe a company that sells online, not one that serves online sellers.
Rerun the test whenever you change the rubric, the extraction prompt, or the model version.
Frequently asked questions
Can a website prove buying intent?
No. A website shows visible fit signals, such as what a company sells and who it sells to. Buying intent means a company is actively looking for a solution now, and a public website rarely shows that. Treat website scores as fit evidence and look for intent signals in other sources.
What is the difference between ICP fit and lead readiness?
ICP fit asks whether a company matches the kind of customer you serve best. Lead readiness asks whether that company is ready to talk or buy right now. Website evidence supports fit scoring. Readiness usually depends on engagement, timing, and conversations, which your sales process tracks separately.
How do I score companies with incomplete data?
Keep missing facts as unknown instead of scoring them as zero. Ask a coverage question for each dimension, and route companies with no evidence on an important dimension to review. A reviewer can check another page or mark the company as unscored. This keeps gaps from pushing good accounts down.
Does MrScraper provide contact data?
This workflow uses only public company facts, such as descriptions, products, customer types, and sales channels, with their source URLs. It does not collect personal contact details. Extract only the fields you need from pages you are allowed to access, and follow the privacy rules that apply to your data.
Can Jev replace a sales qualification team?
No. Jev is decision support. It gives your team a consistent first pass over many companies, with scores tied to evidence. People still review unclear cases, set the rubric and weights, and make the final call. Use labeled examples to check that the scores match your team's judgment.
Facts about Jev checked against TypeSafe's official documentation on October 13, 2026. Jev is in early access, and its API and limits may change. The rubric, weights, and thresholds in this guide are examples, not tested recommendations.
Summarize this post
Open it in your assistant of choice with the prompt ready to send.
Take a Taste of Easy Scraping!
Find more insights here

Classify Web Data with Jev and MrScraper: A Python Tutorial
Build a Python workflow that extracts web records with MrScraper, classifies them with Jev, validate…

What Is Jev? A Practical Guide for Web Data Teams
Learn what Jev does, how Choice, Score and Noul work, and where structured web data fits into classi…

HTML to Markdown: Converting Scraped Web Pages for LLM Training
Learn how to convert html to markdown for LLM training. Reduce token usage by 90% and improve RAG ac…