Every delivery is one JSONL file (one VideoObject per line) plus, for Growth and Scale, four joinable Parquet tables (videos, people, brands, products). Scale adds two more tables (industry_claims and statements), for six Parquet tables in total. The JSONL record is denormalized; Parquet is normalized for warehouse ergonomics. Current schema version is 3.2.0.
No VidScore quality score is included in the feed. That is an internal operational metric and is not published to any tier.
Data provenance
Source data is publicly available YouTube content, including video metadata and public captions. All entity extraction, classification, and scoring are performed by VidScore's proprietary AI pipeline on VidScore-controlled infrastructure. No third-party data enrichment services are used. Every record is traceable to a specific YouTube video via video_url.
Field nullability
Fields marked *Required: Yes* are guaranteed present and non-null on every record. Optional fields may be null. Fields gated to higher tiers return null on lower-tier deliveries, see [Tier Comparison and Field Gating](/help/enterprise-portal/tier-comparison-and-field-gating).
Freshness
Deliveries are produced weekly (Growth and Scale, Monday mornings UTC) or biweekly (Starter). Each delivery contains videos published during the prior delivery period. See [Delivery Cadence, File Formats, and What Arrives When](/help/enterprise-portal/delivery-cadence-and-format) for the full schedule.
Example record
Abbreviated for readability. Shows the full nesting: channel, iab, entities.people, entities.brands, entities.products, topics. Field types and every enum value are documented in the Field Index below.
{
"schema_version": "3.2.0",
"entity_type": "VideoObject",
"extracted_at": "2026-04-21T09:15:00Z",
"video_id": "dQw4w9WgXcQ",
"video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"title": "iPhone 17 Pro, honest review after 30 days",
"title_translated": null,
"language": "en",
"published_at": "2026-04-17T14:22:08Z",
"duration_seconds": 847,
"view_count": 2840000,
"channel": {
"id": "UCBJycsmduvYEL83R_U4JriQ",
"name": "MKBHD",
"handle": "@mkbhd",
"subscriber_count": 19400000,
"is_verified": true
},
"iab": {
"content": [{
"unique_id": "611",
"name": "Smartphones",
"tier1": "Technology & Computing",
"tier2": "Consumer Electronics",
"tier3": "Smartphones",
"tier4": null,
"confidence": 0.96,
"is_scd": false
}],
"content_form_factor": "Video",
"is_sensitive_content": false,
"openrtb_cat": ["611"],
"openrtb_cattax": "2"
},
"content_type": "review",
"industries": ["consumer_electronics"],
"entities": {
"people": [{
"entity_type": "Person", "name": "Marques Brownlee",
"role": "host", "confidence": 0.95,
"sameAs": ["https://www.wikidata.org/wiki/Q18810450"]
}],
"brands": [{
"entity_type": "Brand", "name": "Apple", "is_sponsor": false,
"sentiment": 0.62, "sentiment_label": "positive",
"context_role": "review", "prominence_level": "primary"
}],
"products": [{
"entity_type": "Product", "name": "iPhone 17 Pro",
"parent_brand": "Apple", "sentiment": 0.55,
"price_mentioned": true, "estimated_price_cents": 119900, "currency": "USD"
}]
},
"topics": [{
"slug": "smartphones",
"label": "Smartphones",
"unique_id": "611",
"name": "Smartphones",
"tier1": "Technology & Computing",
"tier2": "Consumer Electronics",
"tier3": "Smartphones",
"tier4": null,
"confidence": 0.94
}],
"summary": "Long-term review of the iPhone 17 Pro covering battery, camera, and build quality."
}Field Index
Record Metadata
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
schema_version | string | Yes | Feed schema version | "3.2.0" |
entity_type | string | Yes | Always "VideoObject" | "VideoObject" |
extracted_at | ISO 8601 | Yes | When this record was assembled | "2026-04-21T09:15:00Z" |
Video Metadata
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
video_id | string | Yes | YouTube 11-char video ID (primary key) | "dQw4w9WgXcQ" |
video_url | string | Yes | Canonical watch URL | "https://www.youtube.com/watch?v=dQw4w9WgXcQ" |
title | string | Yes | Current video title at scan time | "iPhone 17 Pro, honest review" |
published_at | ISO 8601 | Yes | Original publish timestamp | "2026-04-17T14:22:08Z" |
last_checked | ISO 8601 | Yes | Most recent VidScore analysis timestamp | "2026-04-21T09:15:00Z" |
duration_seconds | integer | Yes | Total runtime in seconds (matches OpenRTB video + IAB CTV spec; convert to minutes downstream if needed) | 847 |
view_count | integer | Yes | View count at last_checked | 2840000 |
thumbnail_url | string | Yes | YouTube hqdefault or custom thumb | "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg" |
Channel Details
| Field | Type | Description | Example |
|---|---|---|---|
channel.id | string | YouTube channel ID | "UCBJycsmduvYEL83R_U4JriQ" |
channel.name | string | Display name | "MKBHD" |
channel.handle | string | YouTube @handle | "@mkbhd" |
channel.url | string | Channel URL | "https://www.youtube.com/@mkbhd" |
channel.subscriber_count | integer | null | Subs at last scan | 19400000 |
channel.thumbnail_url | string | Avatar URL | "https://yt3.ggpht.com/..." |
channel.is_verified | boolean | YouTube verification badge | true |
IAB Classification
Field names match IAB Content Taxonomy 3.1 published TSV columns 1:1. unique_id is the IAB row's "Unique ID" (the OpenRTB cat value), and tier1-tier4 are the breadcrumb path from root to the classified node.
| Field | Type | Description | Example |
|---|---|---|---|
iab.content | array of objects | IAB Content Taxonomy 3.1 classifications. Each element identifies one IAB node. Fields per element: unique_id, name, tier1, tier2, tier3, tier4, confidence (0-1), is_scd (boolean) | See example record above |
iab.content[].unique_id | string | IAB Unique ID (the OpenRTB cat value) | "611" |
iab.content[].name | string | IAB Name column for the classified node | "Smartphones" |
iab.content[].tier1–tier4 | string | null | IAB Tier 1/2/3/4 breadcrumb path. Null when the node doesn't extend that deep. | "Technology & Computing" |
iab.ctv_genre | string | null | IAB CTV Genre Mapping (for show/episodic content) | "Documentary" |
iab.podcast_genre | string | null | IAB Podcast Genre Mapping | "Technology" |
iab.content_form_factor | enum | One of: Video, Show, Episodic Show, Event, Clip, Movie | "Video" |
iab.is_sensitive_content | boolean | True if any IAB category on the video is SCD | false |
iab.openrtb_cat | array of strings | Flat array of unique_id values, OpenRTB-ready (cattax=2) | ["611"] |
iab.openrtb_cattax | string | OpenRTB cattax value, hard-coded "2" (IAB Content 3.x) | "2" |
Topics
Topics is a list of canonical IAB-aligned subjects substantively discussed in the video. Drawn from a curated 68-topic subset of IAB Content Taxonomy 3.1, each topic identifies one IAB node. Field names match IAB published TSV columns 1:1.
| Field | Type | Description | Example |
|---|---|---|---|
topics | array of objects | empty | Up to 5 topics per video. Empty array if no topic met the substantive-discussion threshold. Topics with confidence < 0.70 are filtered. | See example record above |
topics[].slug | string | URL-safe topic identifier (e.g. "smartphones") | "smartphones" |
topics[].label | string | Display label (= IAB Name) | "Smartphones" |
topics[].unique_id | string | IAB Unique ID for the topic node | "611" |
topics[].name | string | IAB Name column for the classified node | "Smartphones" |
topics[].tier1–tier4 | string | null | IAB Tier 1/2/3/4 breadcrumb path. Null when the node doesn't extend that deep. | "Technology & Computing" |
topics[].confidence | float 0-1 | Extraction confidence. Always >= 0.70 (lower-confidence topics are dropped). | 0.94 |
Content Taxonomy
| Field | Type | Description | Example |
|---|---|---|---|
content_type | enum | VidScore's 17-vertical content-type axis | "review" |
subcategory | string | null | Finer-grained label (optional) | "long-form review" |
industries | array of strings | Content-derived industry tags (1-5) from the 20-slug canonical list. Classified by Gemini from narrative intent + target audience, NOT brand rollup. A finance tutorial discussing a fast-food chain's stock tags financial_services, never food_beverage. Single-topic videos typically emit 1 tag; long-form podcasts covering several industries can emit up to 5, use per-entry confidence in video_industries_detail to filter by relevance. | ["financial_services"] |
video_industries_detail | array | null | Audit trail (Scale tier). Contains {industry, confidence, reasoning} per slug so buyers can filter by confidence threshold. | [{"industry":"financial_services","confidence":0.92,"reasoning":"HYSA tutorial, target audience = retail investors"}] |
*content_type enum values:* conversation, review, news, analysis, tutorial, education, storytelling, entertainment, performance, showcase, competition, lifestyle, food, travel, advocacy, sports, other.
*industries canonical 20 slugs:* consumer_electronics, gaming, automotive, software_saas, financial_services, beauty_skincare, fashion_apparel, food_beverage, qsr_dining, health_wellness, streaming_entertainment, travel_hospitality, luxury_goods, outdoor_sporting, education, baby_parenting, pet_products, real_estate, home_appliances, retail_mass_merchant. As of schema 3.1.0, every record also carries industries_detail — a parallel array of {industry, confidence} objects letting buyers filter by classifier confidence.
> Industry vs Brand Category. videos.industries describes the video's content theme. Each brand in entities.brands[] carries its own category describing the brand's core business. These are computed independently. A stock-picking video about McDonald's tags financial_services at the video level while McDonald's the brand carries qsr_dining.
People
| Field | Type | Description | Example |
|---|---|---|---|
entity_type | string | Always "Person" | "Person" |
id | string | VidScore UUID (stable across videos) | "e1b2c3..." |
name | string | Canonical person name | "Marques Brownlee" |
role | enum | See role values below | "host" |
confidence | float 0-1 | Extraction confidence (baseline >= 0.85, transcript >= 0.70) | 0.95 |
sameAs | array of strings | External IDs (Wikidata QID, YouTube handle) | ["https://www.wikidata.org/wiki/Q18810450"] |
statements | string | Statements attributed to this person | "Apple nailed the battery." |
last_enriched_at | ISO 8601 | null | Last KG enrichment timestamp | "2026-04-20T12:00:00Z" |
google_kg_id | string | Google Knowledge Graph identifier for the resolved person (Starter). Public reference ID. | "/g/11abc" |
occupation | string | Resolved occupation of the person (Growth) | "YouTuber" |
expertise | string | Resolved domain expertise (Growth) | "consumer tech reviews" |
presence_status | enum | Presence tier: confirmed / probable / rejected (Growth) | "confirmed" |
presence_score | number | Confidence the person is actually present, 0 to 1 (Growth) | 0.98 |
is_true_guest | boolean | True if a genuine guest vs a passing mention (Growth) | true |
sentiment_score | number | How the person is portrayed, -1 to 1 (Growth) | 0.4 |
sentiment_label | enum | Portrayal sentiment: positive / neutral / negative (Growth) | "positive" |
sentiment_context | string | Short text on how the person is portrayed (Growth) | "Credited as the expert voice." |
The sameAs array already carries the person's Wikidata QID and Wikipedia URLs, and google_kg_id adds the Google Knowledge Graph reference ID. These are public reference identifiers only. VidScore never delivers social handles or contact details.
*role enum:* host, co_host, panelist, guest, narrator, primary_character, performer, mentioned, clip_featured, cameo.
Brands
| Field | Type | Description | Example |
|---|---|---|---|
entity_type | string | Always "Brand" | "Brand" |
name | string | Canonical brand name | "Apple" |
is_sponsor | boolean | True if brand is the video sponsor | false |
sentiment | float -1.0 to 1.0 | Sentiment score | 0.62 |
sentiment_label | enum | positive | negative | neutral | mixed | "positive" |
sentiment_context | string | Human-readable sentiment context (Growth/Scale) | "Reviewer praises battery life." |
context_role | enum | See below | "review" |
prominence_level | enum | primary | secondary | background (Growth/Scale) | "primary" |
iab_ad_product | array of objects | IAB Ad Product Taxonomy 2.0. Each element identifies one IAB node with fields: unique_id, name, tier1, tier2, tier3, tier4, confidence. Field names match IAB published TSV columns 1:1. | [{ "unique_id": "...", "name": "Smartphones", "tier1": "Electronics", "tier2": "Mobile Phones", "tier3": "Smartphones", ... }] |
sponsorship_type | enum | pre_roll | mid_roll | post_roll | integrated | branded_content | "integrated" |
disclosure_present | boolean | True if FTC-compliant disclosure detected | true |
affiliate_url | string | Affiliate link surfaced in the mention, when present (Growth) | "https://aff.example/x" |
statements | string | Statements about this brand | "Apple announced..." |
*context_role enum:* sponsor, product_use, analysis, news, opinion, review, tutorial, comparison, incidental.
Products
Products mirror brands and add product-specific fields:
| Field | Type | Description | Example |
|---|---|---|---|
name | string | Product name | "iPhone 17 Pro" |
parent_brand | string | null | Brand that owns the product | "Apple" |
is_sponsored | boolean | True if featured in a sponsorship | false |
sentiment | float -1.0 to 1.0 | Per-product sentiment | 0.55 |
price_mentioned | boolean | True if price was mentioned | true |
estimated_price_cents | integer | null | Price in cents | 119900 |
currency | string | ISO 4217 currency code | "USD" |
comparison_products | array of strings | Products this was compared to | ["Samsung Galaxy S26", "Pixel 10"] |
winner_declared | string | null | Winner of a declared comparison | "iPhone 17 Pro" |
confidence | number | Detection confidence for the product mention, 0 to 1 (Starter) | 0.9 |
(Products also carry iab_ad_product, context_role, prominence_level, sponsorship_type, and statements, same shape as brand entities.)
Topics
| Field | Type | Description | Example |
|---|---|---|---|
slug | string | Stable topic slug | "smartphone-review" |
label | string | Display label | "Smartphone review" |
path | array | null | Topic hierarchy path | ["Technology", "Mobile", "Smartphone review"] |
confidence | float 0-1 | Match confidence | 0.94 |
match_type | enum | exact, alias, semantic | "exact" |
Summary
| Field | Type | Description |
|---|---|---|
summary | string | AI-generated natural-language summary of the video |
Two Statement-Shaped Tables
VidScore ships two arrays that contain things said in a video. They are deliberately separate because they are at different grains and serve different buyers. Per Kimball dimensional modeling, mixing grains in one fact table is an anti-pattern.
| Table | Grain | Built for | Typical row count/video |
|---|---|---|---|
video_statements (Scale, JSONL plus statements.parquet) | One row per structured claim (subject / verb / object) | Knowledge-graph / competitive-intel / trading-signal customers who need "who said what about whom" as queryable data | 5-30 |
industry_claims (Scale, Parquet only) | One row per normalized dimensional brand claim (brand × industry × dimension) | Brand intelligence / BI customers who want "how is Brand X perceived on build_quality across all automotive content" | 0-20 |
Same utterance can appear in both tables. That is intentional. Each shape is optimized for a different query pattern, and Parquet columnar storage makes it cheap.
Video Statements SCALE TIER
Array of statement-level intelligence: claims made in the video. No timestamps and no speaker attribution, YouTube auto-captions do not support diarization. Statements strongly associated with a named person are echoed in that person's statements field instead. As of schema 3.2.0, Scale deliveries also ship these as a statements.parquet table (one row per statement, joinable to videos.parquet on video_id, with columns video_id, text, kind, subject_type, subject_name, object_type, object_name, stance, sentiment, strength, topics, risk_flags).
| Field | Type | Description |
|---|---|---|
text | string | The statement text |
kind | string | null | Statement classification (e.g., opinion, claim, prediction) |
subject | { type, name } | Subject entity type + name |
object | { type, name } | Object entity type + name |
stance | string | null | Stance taken (pro, against, neutral) |
sentiment | enum | positive | negative | neutral | mixed |
strength | float | null | Strength of assertion (0-1) |
topics | array of strings | Topic tags |
risk_flags | array of strings | Risk flags (e.g., controversial, medical_advice) |
Industry Claims SCALE TIER
Scale-tier Parquet deliveries include a fifth file, claims.parquet, joinable to videos.parquet on video_id.
| Column | Type | Description | Example |
|---|---|---|---|
video_id | string | Foreign key to videos | "dQw4w9WgXcQ" |
brand_name | string | Brand the claim is about | "Apple" |
target_product | string | The specific product a claim is anchored to, when applicable (Scale) | "MacBook Neo" |
target_level | enum | Whether the claim is anchored at brand or product level (Scale) | "product" |
industry | string | Industry slug | "consumer_electronics" |
dimension | string | Industry-specific claim dimension (e.g., build_quality, reliability, performance, value) | "build_quality" |
claim | string | Normalized claim text | "Titanium frame feels premium." |
raw_quote | string | Original transcript quote | "The titanium frame is lighter than last year and feels way more premium." |
sentiment | enum | positive | negative | neutral | mixed | "positive" |
sentiment_score | float -1 to 1 | Numeric sentiment | 0.78 |
confidence | float 0-1 | Extraction confidence | 0.89 |
Delivery specification
- Transport. Signed URL (AWS S3-backed Supabase Storage), valid for 7 days from generation. Regenerate from the portal if a URL expires before you download.
- Path pattern.
{customer_id}/{YYYY-W##}/vidscore-data-{YYYY-W##}.jsonlExample:org-abc123/2026-W17/vidscore-data-2026-W17.jsonl - Manifest. Each delivery ships with a companion
vidscore-data-{YYYY-W##}-manifest.jsoncontainingdelivery_id,period_start,period_end,schema_version, record counts, industries included, and a quality scorecard. - Parquet (Growth, Scale). Normalized tables
videos.parquet,people.parquet,brands.parquet,products.parquetall joinable onvideo_id. Scale addsindustry_claims.parquetandstatements.parquet, for six Parquet tables in total. - Retention of delivered files. 90 days (Starter), 180 days (Growth), 365 days (Scale), measured from each delivery's original date. See [Data Governance, Quality Checks, and Retention](/help/enterprise-portal/data-governance-and-retention) for retention mechanics.
Schema versioning
Current: 3.2.0. Minor versions (3.x → 3.y) only add fields; they never remove or rename existing fields. A parser that ignores unknown keys stays forward-compatible. A major version bump (3.x → 4.x) requires 90 days of written notice. Every JSONL record is validated against the published JSON Schema before it leaves our infrastructure. For quality rules, validation checks, and retention policies, see [Data Governance, Quality Checks, and Retention](/help/enterprise-portal/data-governance-and-retention).
Detailed reference
What you can expect
- Full video and channel metadata in every record
- IAB Content Taxonomy 3.1 + OpenRTB category IDs (cattax=2) for DSP-native ingestion
- IAB Ad Product Taxonomy 2.0 on brand and product entities
- Sentiment score (-1 to 1), sentiment_label, and sponsorship detection with FTC disclosure flag
- Entity disambiguation via Wikidata sameAs links with confidence scores
- Statement-level intelligence (JSONL plus statements Parquet table) and industry_claims Parquet table (Scale)
Limits
- VidScore internal quality score (subjective operational metric, not published to any tier)
- Speaker diarization inside video_statements (auto-captions do not support it)
- Raw transcript text (derived intelligence only, not the source captions)
- sentiment_context, prominence_level, iab_ad_product, and sponsorship detail on Starter deliveries
- video_statements and industry_claims on Starter deliveries
Important context
The schema is additive by contract. Minor version bumps (2.3.0 to 2.4.0) only add fields, they never remove or rename them. If you write your parser to ignore unknown keys you will not need to touch it when we ship a minor version. A major version bump (2.x to 3.x) would be communicated 90 days in advance with a migration guide.
Last updated 2026-04-24