Trust · Methodology
How a company row gains supported web intelligence
Start with a CSV or spreadsheet your team already uses. Kaiju researches each approved company website and returns the same row with supported website and technology data, plus a clear status for anything it could not establish.
Start with the spreadsheet
Suppose your CSV has one row for Lumen Systems. It already has a record ID, website, and company name. Kaiju keeps those columns and adds new ones beside them.
Start with the spreadsheet
Watch one uploaded row come back with new fields
Kaiju keeps the original columns, then adds company, technology, and evidence columns beside them.
companies.csv
One company from the uploaded file
0 of 3 fields added
Original file
record_id
company_1842
website
lumen.example
company_name
Lumen Systems
Updated file
matched_website
…
waiting
technologies
…
waiting
evidence
…
waiting
The thread we will follow
How did the returned technologies = Shopify cell earn its place in the row?
First, Kaiju records what it sees
A browser sees a Shopify-owned script URL on a public product page. Kaiju stores that literal value, the page it came from, and the time it was collected. That record is an observation.
The observation does not say “this company uses Shopify.” It only says what the source exposed. Keeping that distinction lets Kaiju rerun better detector rules later without visiting the page again.
One observation
Kaiju first records what the page exposed
At this point Kaiju has a script URL, a page, and a time. It has not called the site a Shopify customer yet.
Public product page
<script
src="https://cdn.shopify.com/…"
></script>
Observation
- value
- https://cdn.shopify.com/shopifycloud/storefront/assets/storefront.js
- page
- https://lumen-goods.example/products/aurora-lamp
- collected
- 2026-07-22T14:32:18.000Z
- collector
- cli-browser-browser-document
- interface
- browser-browser
The brighter fields carry the core lesson. The dim fields remain available for audit.
Open the complete normalized record
{
"kind": "scriptSrc",
"interface": "browser-browser",
"collector": "cli-browser-browser-document",
"target": {
"url": "https://lumen-goods.example/products/aurora-lamp",
"hostname": "lumen-goods.example"
},
"observedAt": 1784730738000,
"value": "https://cdn.shopify.com/shopifycloud/storefront/assets/storefront.js",
"attributes": {
"routeFamily": "commerce.product"
},
"source": {
"source": "browser",
"kind": "browser_capture",
"url": "https://lumen-goods.example/products/aurora-lamp",
"route_family": "commerce.product",
"browser": {
"page_url": "https://lumen-goods.example/products/aurora-lamp",
"capture_phase": "document"
}
}
}The same observation as a record
Core fields are brighter
{
"kind": "scriptSrc",
"value": "https://cdn.shopify.com/…",
"page": "https://lumen-goods.example/products/aurora-lamp",
"observedAt": "2026-07-22T14:32:18Z",
"collector": "cli-browser-browser-document",
"interface": "browser-browser"
}A rule names the evidence
A detector compares the observed URL with a specific Shopify rule. When the URL contains the expected Shopify host, Kaiju emits named detection evidence. When it does not match, the observation remains, but no Shopify detection appears.
One detector rule
A rule gives the observation a name
The collected URL stays literal. Kaiju reports Shopify only when the Shopify rule matches it.
Observation
https://cdn.shopify.com/shopifycloud/storefront/assets/storefront.js
Registry rule
URL contains cdn.shopify.com
shopify:scriptSrc:1
Shopify detected
Evidence record emitted
See the technical DetectionResult
{
"technologyId": "shopify",
"name": "Shopify",
"website": "https://shopify.com",
"category": "content",
"tags": [
"platform-cms-builder"
],
"confidence": {
"value": 98,
"level": "high"
},
"evidence": [
{
"kind": "scriptSrc",
"ruleId": "shopify:scriptSrc:1",
"ruleDescription": "Script source URL matches a known technology marker.",
"matchedValue": "https://cdn.shopify.com/shopifycloud/storefront/assets/storefront.js",
"confidence": 100,
"direct": true,
"source": {
"schema_version": 1,
"source": "browser",
"kind": "browser_capture",
"url": "https://lumen-goods.example/products/aurora-lamp",
"observed_at": "2026-07-22T14:32:18.000Z",
"route": "/products/aurora-lamp",
"route_family": "commerce.product",
"browser": {
"page_url": "https://lumen-goods.example/products/aurora-lamp",
"capture_phase": "document"
}
}
}
]
}A fact makes the answer reusable
The detector result is still technology-specific output. Kaiju converts it into a consistently defined fact with a stable meaning: technology.presence = Shopify. The fact keeps the supporting observation ID, confidence, extractor version, and public page or signal.
Other extractors can create other fact kinds, such as commerce.product_page.present. The shared fact contract lets the enrichment layer read both without knowing how each collector worked.
One fact
The fact is the reusable claim
Kaiju turns source-specific evidence into a stable claim that an enrichment field can read later.
Supporting observation
https://cdn.shopify.com/shopifycloud/storefront/assets/storefront.js
Collected from commerce.product
DomainFact
- What does this claim mean?
- technology.presence
- What is the answer?
- Shopify
- How is it supported?
- observed_resource
- Which observation supports it?
- obs_8f1d1f4a
The observation describes what the collector saw. The fact states what Kaiju can safely reuse: Shopify is present.
Open every fact field
{
"schemaVersion": 1,
"id": "fact_b7d996e2",
"runId": "run_20260722_1432",
"crawl": "browser-2026-07-22",
"domain": "lumen-goods.example",
"subject": {
"type": "domain",
"key": "lumen-goods.example"
},
"factKind": "technology.presence",
"value": "Shopify",
"objectType": "software",
"assertion": "observed_resource",
"confidence": 0.98,
"extractorId": "facts.detection-bridge",
"extractorVersion": "1.0.0",
"factKindVersion": 1,
"sourceKind": "browser_capture",
"sourceObservationId": "obs_8f1d1f4a",
"attributes": {
"sourceSurface": "scriptSrc",
"matchedHost": "cdn.shopify.com"
},
"source_provenance": {
"schema_version": 1,
"source": "browser",
"kind": "browser_capture",
"url": "https://lumen-goods.example/products/aurora-lamp",
"observed_at": "2026-07-22T14:32:18.000Z",
"route": "/products/aurora-lamp",
"route_family": "commerce.product",
"browser": {
"page_url": "https://lumen-goods.example/products/aurora-lamp",
"capture_phase": "document"
}
}
}The fact system protects the meaning
A fact is useful only when its meaning stays stable. The fact-kind registry defines which subject, values, assertions, and versions are valid. Validation rejects records that do not satisfy that contract.
Aggregates can group supported facts for one website and research run while retaining the supporting fact IDs. The export reads those records and writes the customer-facing field.
Why facts form a system
The same contract protects the claim from collection to export
The registry defines the meaning. The fact carries the supported answer. The aggregate and export keep the source fact identifiers.
1
Contract
Defines which subject, value, and assertions are valid.
technology.presence · v1
2
Supported finding
Stores the answer together with the public observation that supports it.
Shopify · 98%
3
CSV column
Adds the supported value to the returned company row.
technologies = Shopify
The sample aggregate still cites 2 source facts.
Open the registry and aggregate records
{
"id": "technology.presence",
"label": "Technology presence",
"factKindVersion": 1,
"facets": [
"technology",
"service_inventory"
],
"subjectType": "domain",
"objectType": "software",
"allowedAssertions": [
"declared_by_page",
"observed_resource",
"inferred"
],
"dedupeFields": [
"domain",
"crawl",
"subject.type",
"subject.key",
"factKind",
"value"
],
"aggregation": {
"id": "site_technology_inventory",
"grain": [
"domain",
"crawl"
]
}
}{
"schemaVersion": 1,
"id": "site_technology_inventory:crawl=browser-2026-07-22&domain=lumen-goods.example",
"runId": "run_20260722_1432",
"crawl": "browser-2026-07-22",
"domain": "lumen-goods.example",
"aggregationId": "site_technology_inventory",
"aggregationVersion": 1,
"grain": {
"domain": "lumen-goods.example",
"crawl": "browser-2026-07-22"
},
"factCount": 2,
"supportCount": 2,
"factKindCounts": {
"technology.presence": 2
},
"factValueCounts": {
"technology.presence": {
"Shopify": 1,
"Klaviyo": 1
}
},
"routeFamilies": [
"commerce.product"
],
"sourceFactIds": [
"fact_4f2885c1",
"fact_b7d996e2"
],
"createdAt": "2026-07-22T14:33:02.000Z"
}AI is not the evidence layer
AI may help map an input column or explain a result, but the returned field must still trace back to a public observation, a maintained detector or extractor, a consistently defined fact, a completed-check decision, and the supporting source. A plausible generated answer is not enough.
Missing does not always mean no
A positive match can support present. A missing match is harder. Kaiju can return not detected only after it collected the right page, ran the responsible extractor, and had access to a public surface where the signal could appear.
When one of those checks is incomplete, the returned value stays unknown. This keeps a blocked or incomplete crawl from becoming a false negative in the CSV.
One missing field
Blank only means “not detected” after the right checks ran
Turn off one check and the answer becomes unknown. Turn on positive evidence and the answer becomes present.
Returned value
The eligible public surfaces were checked and no provider marker was found.
The returned cell keeps its evidence
The CSV is the delivery surface, but it is not the end of the record. A value Kaiju added can still point to the fact behind it and the public observation that supports that fact.
One returned cell
The exported value can still point back to its source
Select a field. The path stays short: returned cell, supported fact, public observation.
Returned CSV cell
technologies
Shopify; Klaviyo
Supported fact
technology.presence
Shopify
Public observation
scriptSrc
https://cdn.shopify.com/shopifycloud/storefront/assets/storefront.js
Kaiju reads the canonical technology.presence facts produced for this domain and crawl.
Where public evidence stops
Kaiju can report what a public web property exposed during a named collection. It cannot prove private contract value, internal ownership, satisfaction, budget, purchase intent, or integrations hidden behind authentication or server-side execution.
| Returned state | What it means |
|---|---|
| Present | Collected evidence supported the named claim. |
| Not detected | The eligible public check completed and found no matching evidence. |
| Unknown | The required checks could not support either conclusion. |