Domain scanning
A vendor's customer hostnames show up in public Certificate Transparency logs. Scan an ERP or accounting apex, drop the vendor's own infrastructure names, then look up each remaining label until it resolves to a company. That company is a customer of the scanned vendor. It is not yet a Naologic prospect.
The hostname is an installed-base hypothesis. It is not proof of a problem, a buying process, or a system of record we may state on a call. Qualification against market, vertical, size, and sites still has to happen. Enrichment never becomes that proof. See Sales stack.
Context
Use this page when the job is to build a list from who already runs a named
system, not from NAICS alone. Certificate Transparency is one digital
artifact for that job. It sits beside job-post system names
(SG_016) and the audience
systems_of_record dimension in
variables.yaml.
Do not use this page as a generated GTM guide, a competitor profile, or a canonical signal record. A scan hit does not create an account in Salesforce until a person accepts the match.
The original working notes on this page were:
- Query crt.name for an apex such
as
slack.comorsalesforce.com - Get the domain, crawl the page, qualify it
- Enumerate ERPs, including products that are winding down (QuickBooks Desktop)
- Use our competitor list as seeds
- Pin whatever else reveals installed base
Those notes are the seed. The rest of this page is the descent.
Guidance
1. High altitude — why this works
Multi-tenant vendors issue TLS certificates for hostnames of the form
{tenant}.{vendor-apex}. Those names are logged in Certificate Transparency.
The leftmost label is often the customer's brand, a slug of their name, or a
vanity they chose at signup.
That gives us a question we can ask before a call: "this establishment appears
on {vendor}'s certificate set." It does not give us the answer to "they have
problem P." It does not give us the right to say they use that system today —
certs linger, partners appear, and test tenants exist.
Three consequences follow:
- Scan vendors, not industries. The industry filter happens after lookup.
- The vendor is already a
systems_of_recordhypothesis. Record it as unverified until a website, job post, or the buyer confirms it. - Slack and Salesforce in the notes are method examples. Their tenant sets are huge and mostly off ICP. Scan them to learn the API. Do not treat the dump as a manufacturing list.
2. Middle altitude — what to pin
Build a vendor apex catalog before scanning. "Every ERP on earth" is a research backlog, not a one-shot extract. Prefer sources we already own, then widen.
Class A — displacement systems we already name. Map each catalog value in
variables.yaml system_of_record to one or more public apexes we can query.
The catalog order is the displacement priority. Hostnames are a hypothesis
that the named class is present, not a completed systems_of_record list.
| Catalog value | Why it matters | CT scan | Notes |
|---|---|---|---|
spreadsheets | Common with QuickBooks on M1 audiences | No | No tenant hostname |
quickbooks | Ledger many plants will not leave | Partial | Online and hosted products may appear under Intuit / QuickBooks apexes. Desktop does not look like {shop}.quickbooks.com |
industry_specific | Includes manufacturing ERPs such as Global Shop | Yes, per product apex | Confirm the product's real SaaS hostname, not the marketing site only |
sage | Accounting / ERP displacement | Yes, per product | Multiple products, multiple apexes |
epicor | Manufacturing ERP | Yes, per cloud product | |
infor | Manufacturing ERP | Yes, per cloud product | |
dynamics | Microsoft business apps | Yes, per cloud product | |
netsuite | Upper-middle displacement | Yes | |
sap | Usually out of our size band | Yes | Still useful as a negative filter after lookup |
custom_built | Homegrown | No | Use job posts and the website |
unknown | No system identity yet | n/a | Do not invent a value from a weak slug |
Class B — deprecating products. A sunset (QuickBooks Desktop, an old on-prem SKU) is a reason they might move, not a CT shape. Confirm the vendor's current lifecycle page before anyone says "Desktop is going away" on a call. Pair the sunset with another artifact: job posts, community threads, or a buyer sentence. Do not use deprecation as urgency theater.
Class C — named competitors. Start from
Competitors. Today that is
Global Shop. Add an apex only
when we know the product's customer-hostname pattern. Audience
competitor_ids still require account or buyer confirmation before competitive
language goes on a call.
Class D — adjacent SaaS, method and spillover. FreshBooks, Xero, and similar
accounting hosts produce noisy tenant dumps. The working dump in
f.md is a FreshBooks harvest: thousands of {label}.freshbooks.com
names, mixed with vendor infrastructure (careers, status, support). Use
it to test the parser. Do not confuse a FreshBooks tenant with a plastics
plant.
Class E — method drills. slack.com and salesforce.com on crt.name show
the query shape. They are not M1 seeds.
What else to pin (only if it reveals installed base):
- Job posts that name a system (SG_016)
- Careers pages and integration directories on the company's site after lookup
- Partner locators and "customer stories" on the vendor site (separate from CT; treat as marketing, not a cert)
- DNS and MX that still point at a vendor after the company domain is known
Do not pin: employee personal blogs, parked slugs, or anything that requires logging into the vendor product.
3. Low altitude — the scanner
The scanner is one machine. Vendor apexes go in. Company candidates come out.
Nothing in the machine is allowed to mark qualification as list_candidate
without the lookup and ICP steps.
3.1 Inputs
seed_apexes[]— vendor hostnames, each withclass(displacement|deprecating|competitor|adjacent|method) and optionalsystem_of_recordcatalog valuevendor_label_denylist— leftmost labels that are the vendor, not a customerrate_limit— wait between crt.name calls and between company crawls
3.2 Harvest
For each apex in seed_apexes:
GET https://crt.name/v1/search?apex={apex}
Worked method URLs:
https://crt.name/v1/search?apex=slack.comhttps://crt.name/v1/search?apex=salesforce.com
Parse every certificate name in the response into FQDNs. Keep names that are
exactly {label}.{apex} or {label}.www.{apex} only if the extra label is
empty of meaning. Drop wildcards that add no tenant (*.{apex} with no
deeper name). Deduplicate case-insensitively.
If the HTTP body is HTML instead of a name list, stop and record the parse failure. Do not invent hostnames.
3.3 Split vendor from tenant
Take the leftmost label. Drop it when it matches the denylist or a pattern that is almost never a company.
Always drop (vendor infrastructure): www, mail, email, api, app,
apps, cdn, static, assets, img, images, m, mobile, go,
login, sso, auth, secure, ssl, vpn, remote, admin, portal,
status, health, monitor, dev, devel, developer, developers,
docs, doc, help, support, kb, community, forum, blog, news,
careers, jobs, partners, partner, sandbox, staging, stage,
test, testing, qa, uat, demo, demos, trial, preview, beta,
alpha, prod, production, internal, intranet, localhost.
Also drop: labels shorter than three characters; pure numerics; labels
that are the vendor brand (freshbooks, salesforce, slack); hyphenated
vendor product names you have listed (woodstitch-billing style only if you
have confirmed they are vendor SKUs — when unsure, send them to lookup with
match_confidence: guessed).
Everything left is a tenant candidate: {label, hostname, apex, class}.
The FreshBooks dump in f.md is this step's output before lookup.
careers.freshbooks.com is vendor. lemonproductions.freshbooks.com is a
tenant candidate.
3.4 Lookup — identify the customer of that vendor
The harvest does not know the company's legal name or its own website. Lookup
is a waterfall. Stop at the first website_confirmed or
zoominfo_confirmed hit. Otherwise keep guessed and move on. Never skip
to Salesforce on guessed alone.
Step A — tenant page (optional, shallow). GET https://{hostname}/ with a
browser-like user agent, no login, no form post. Read title, og:site_name,
visible company name. If the page is a generic vendor login with no customer
name, record tenant_page: vendor_shell and continue. Do not follow into the
authenticated app.
Step B — slug as a corporate domain. DNS lookup for {label}.com, then
.net, .io, .co only if .com is empty. If an A/AAAA or CNAME exists,
fetch the site home page. Compare the visible name to the label (normalized:
strip llc, inc, hyphens). On a plausible match, set
company_domain and match_confidence: website_confirmed.
Step C — search. Query the open web and, when available, ZoomInfo for the label as a company, plus the vendor name as context only in internal notes. Prefer a match that also shows manufacturing, plastics, or a plant — but do not require it yet. ZoomInfo is for identity, size, and phones. It is not proof of a problem.
Step D — crawl the company's own site (the domain from B or C, never the vendor apex). Collect: legal or trade name, locations, what they make or serve, any named systems on careers or integration pages. This is the "get the domain, crawl the page" line from the original notes.
Step E — identity record. Write one hit per tenant candidate:
kind: domain_scan_hit
apex: freshbooks.com
hostname: lemonproductions.freshbooks.com
tenant_label: lemonproductions
vendor_class: adjacent
system_of_record_hypothesis: null
company_name: null
company_domain: null
match_confidence: guessed | website_confirmed | zoominfo_confirmed
tenant_page: vendor_shell | named | error | skipped
qualification: unevaluated
notes: []
system_of_record_hypothesis may be filled only with a
variables.yaml system_of_record value, or left null. Do not invent a new
catalog token because the apex was FreshBooks. Adjacent accounting hosts stay
null until a person maps them (often still unknown on the audience, with
the vendor name only in notes).
3.5 Qualify — still not a prospect
Qualification is a separate pass over hits with
match_confidence other than empty. Use the same gates list-building already
uses, for the market you are filling. For the active vertical core that means
the audience filters, not a vibe. Example from
M1_V2-P1-A01: process (plastic
injection molding), size bands, single site, spreadsheets and QuickBooks as
systems holding part of the operating record.
For each identified company:
- Process / industry. Does the site describe a process we have a vertical for? NAICS in ZoomInfo is a list-building aid, not the result. See Market verticals.
- Size and sites. Headcount and
location_footprintremain unknown until checked. Multi-site changes problem selection (SG_022). - Age / operating debt. SG_025 still gates audiences that assume a system to displace.
- Systems. The scan is one artifact that a vendor relationship existed.
Confirm or leave
unknown. Job posts that name a system are a second artifact (SG_016). - Set
qualification.out_of_scope(wrong process, too small, SAP-only global, etc.),list_candidate(passes the audience filters you are filling), or leaveunevaluatedif lookup failed.
A FreshBooks designer shop and a 40-person molder can share a hostname shape. Only step 3.5 tells them apart.
3.6 Handoff
For list_candidate only:
- Create or match the account in Salesforce. Store the hostname and apex in internal notes, not in outbound copy.
- Enrich contacts in ZoomInfo. Verify before outreach.
- Do not write competitive or "you use X" language until the system is confirmed on the site, a job post, or the call.
- Do not auto-bind
competitor_idsorsystems_of_recordon the audience YAML from a scan.
4. Running the scanner (agent or person)
Run in this order. Do not look up before the denylist. Do not qualify before identity.
- Load
seed_apexesfor this run (one class is enough; method drills stay off the production list). - Harvest and write raw names next to the apex (a dump like f.md is acceptable as raw harvest, not as a target list).
- Apply the denylist. Count dropped vs kept.
- For each kept tenant, run lookup A→D until confirmed or the slug is exhausted.
- Qualify confirmed companies against one audience at a time.
- Hand off
list_candidaterows. Leaveguessedandunevaluatedin the scan file.
Rate-limit crt.name and company sites. Prefer public pages. Never use a customer login, a stolen cookie, or a product exploit to expand a tenant list. Certificate Transparency is the allowed source for names.
5. What this is not
- Proof that the company has P_00010 or any other canonical problem.
- Permission to say on a call that they run Global Shop, QuickBooks, or Salesforce.
- A complete ERP encyclopedia. Class A–C are the working seed; "all ERPs on earth" is ongoing catalog work.
- A substitute for ZoomInfo phone numbers or Salesforce ownership rules.
- Urgent outreach because a product is "deprecated." Confirm lifecycle, then speak plainly.
Evidence and sources
- Method. crt.name Certificate
Transparency search by apex. Example queries in the original notes:
apex=slack.com,apex=salesforce.com. - Raw harvest example. f.md — FreshBooks leftmost labels, mixed vendor infrastructure and tenant candidates. Not a qualified list.
- System vocabulary. variables.yaml
system_of_record. - Signal vocabulary. SG_016 (named system in job posts), SG_022 (multi-site), SG_025 (age / operating debt).
- Enrichment rule. Sales stack — do not treat enrichment as proof of a buyer problem.
- Competitor seed. C_00001_GLOBAL_SHOP.
Related knowledge
- Markets
- Market verticals
- Personas
- Prospecting in GTM guides — section 3, when a guide is generated from an audience
- Research — customer URLs from vendor proof pages, similar pages, and competitor tactics (not CT)
- Sales communication instructions
Change log
- 2026-08-31 — Linked Research for non-CT customer and vendor URL methods.
- 2026-08-22 — Expanded from working notes into a high-to-low scanner: vendor seeds, crt.name harvest, tenant denylist, company lookup waterfall, ICP qualification, Salesforce handoff. Original crt.name URLs kept as method examples.