Fact Check Schema Framework

Use conditional-logic schema generation to keep Fact Check markup aligned with real page state and avoid stale or invalid static templates.

  • Google is phasing out ClaimReview rich results in Search: announced Jun 12, 2025 and removed from Search Console rich result reporting, the Rich Results Test and Search appearance filters on Sep 9, 2025. Expect no fact check rich result.
  • The markup is still supported by Google's Fact Check Explorer and keeps its schema.org meaning for AI assistants and other ClaimReview consumers, so it still earns its place on real fact check articles.
  • Emit it only for a visible fact check with a clear claim and verdict; do not add it to other pages hoping for a Search feature.

When To Use It

Google Search CentralFact Check documentation

Use only on fact check articles that name a specific claim, attribute it to a source outside your organization, and state a clear verdict in the visible article.

Key Implementation Documentation Highlights

  • Google still documents ClaimReview while the phase-out runs. Required: claimReviewed (a short summary of the claim; keep it under 75 characters to limit wrapping on mobile), reviewRating and url (the page hosting the full fact check article).
  • Required on reviewRating (Rating): alternateName, the textual verdict such as False, which is the only rating value shown. name is recommended and used when alternateName is missing.
  • Recommended numeric scale on reviewRating: ratingValue, bestRating and worstRating. worstRating is at least 1 and below bestRating, and ratingValue sits between them inclusive.
  • Recommended: author, the publisher of the fact check (not of the claim), with name and url; and itemReviewed, a Claim with author (who made the claim: name required, sameAs recommended), datePublished, appearance and firstAppearance.
  • Site requirements: several pages marked with ClaimReview, a corrections policy or error reporting, Google News transparency standards, and no political campaigns, parties or elected officials as publishers.

Rules the framework enforces before it emits markup:

  • One ClaimReview per page; a second fact check on the same URL suppresses the markup.
  • No textual verdict (alternateName or name): emit nothing.
  • A numeric scale must satisfy 1 <= worstRating < bestRating and worstRating <= ratingValue <= bestRating, otherwise the markup is suppressed.
  • url is the absolute, self-canonical URL of the article itself, and the claim and conclusion must be readable in the visible article.

Template Approach

const pageData = {
  url: "https://www.example.com/fact-checks/2026/moon-cheese",
  claim: "The moon is made of cheese",
  verdict: "False",
  publisher: "Example Fact Desk"
};

const staticTemplate = {
  "@context": "https://schema.org",
  "@type": "ClaimReview",
  "url": pageData.url,
  "claimReviewed": pageData.claim,
  "reviewRating": { "@type": "Rating", "alternateName": pageData.verdict },
  "author": { "@type": "Organization", "name": pageData.publisher }
};

Conditional-logic Framework

function isAbsoluteUrl(value) {
  if (typeof value !== "string") return false;
  try {
    const url = new URL(value);
    return url.protocol === "https:" || url.protocol === "http:";
  } catch {
    return false;
  }
}

const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
const ISO_DATETIME = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})?$/;

function toIsoDate(value) {
  if (typeof value !== "string" || !ISO_DATE.test(value.trim())) return null;
  return isNaN(Date.parse(value.trim())) ? null : value.trim();
}

function toIsoDateTime(value) {
  if (typeof value !== "string" || !ISO_DATETIME.test(value.trim())) return null;
  // keep the original string so the timezone offset survives
  return isNaN(Date.parse(value.trim())) ? null : value.trim();
}

function compact(value) {
  if (Array.isArray(value)) {
    const items = value.map(compact).filter((item) => item !== undefined);
    return items.length ? items : undefined;
  }
  if (value && typeof value === "object") {
    const out = {};
    for (const [key, item] of Object.entries(value)) {
      const kept = compact(item);
      if (kept !== undefined) out[key] = kept;
    }
    return Object.keys(out).length ? out : undefined;
  }
  if (value === null || value === undefined || value === "") return undefined;
  return value;
}

function buildRating(verdict) {
  // the textual verdict is required: alternateName, or name when alternateName is absent
  const label = (verdict.label || "").trim();
  if (!label) return null;
  const rating = { "@type": "Rating", "alternateName": label, "name": label };

  const { value, worst, best } = verdict;
  const numeric = [value, worst, best].every((n) => typeof n === "number" && isFinite(n));
  if (numeric) {
    // worstRating at least 1 and below bestRating; ratingValue inside the scale
    if (worst < 1 || worst >= best || value < worst || value > best) return null;
    Object.assign(rating, { "ratingValue": value, "worstRating": worst, "bestRating": best });
  }
  return rating;
}

function buildClaim(claim) {
  if (!claim) return null;
  return {
    "@type": "Claim",
    "author": claim.authorName
      ? {
          "@type": claim.authorType === "Person" ? "Person" : "Organization",
          "name": claim.authorName,
          "sameAs": isAbsoluteUrl(claim.authorSameAs) ? claim.authorSameAs : null
        }
      : null,
    "datePublished": toIsoDateTime(claim.datePublished) || toIsoDate(claim.datePublished),
    "appearance": (claim.appearances || []).filter(isAbsoluteUrl),
    "firstAppearance": isAbsoluteUrl(claim.firstAppearance) ? claim.firstAppearance : null
  };
}

function buildClaimReviewSchema(source) {
  // Google is phasing out ClaimReview rich results; emit only for a visible fact check
  // (schema.org semantics, Fact Check Explorer and other consumers)
  if (source.indexable === false) return null;
  if (!isAbsoluteUrl(source.url)) return null;
  if (source.canonicalUrl && source.canonicalUrl !== source.url) return null;
  if (source.verdictVisible !== true) return null; // claim and conclusion must be readable on the page
  if ((source.claimReviewsOnPage ?? 1) !== 1) return null; // one ClaimReview per page

  const claimReviewed = (source.claimSummary || "").trim();
  if (!claimReviewed) return null;
  const reviewRating = buildRating(source.verdict || {});
  if (!reviewRating) return null;

  const schema = {
    "@context": "https://schema.org",
    "@type": "ClaimReview",
    "url": source.url, // the page hosting the full fact check article
    "claimReviewed": claimReviewed, // keep under 75 characters to limit wrapping on mobile
    "reviewRating": reviewRating,
    "author": source.publisher
      ? {
          "@type": "Organization",
          "name": source.publisher.name,
          "url": isAbsoluteUrl(source.publisher.url) ? source.publisher.url : null
        }
      : null,
    "itemReviewed": buildClaim(source.claim)
  };

  return compact(schema);
}

// Usage:
// buildClaimReviewSchema({
//   url: "https://www.example.com/fact-checks/2026/moon-cheese",
//   canonicalUrl: "https://www.example.com/fact-checks/2026/moon-cheese",
//   indexable: true,
//   verdictVisible: true,
//   claimReviewsOnPage: 1,
//   claimSummary: "The moon is made of cheese",
//   verdict: { label: "False", value: 1, worst: 1, best: 5 },
//   publisher: { name: "Example Fact Desk", url: "https://www.example.com/about/corrections-policy" },
//   claim: {
//     authorName: "Square Moon Society",
//     authorSameAs: "https://www.example.org/square-moon-society",
//     datePublished: "2026-04-02",
//     appearances: ["https://www.example.org/posts/moon-facts"],
//     firstAppearance: "https://www.example.org/posts/moon-facts"
//   }
// });

The Output As An Entity Graph

The conditional-logic output above, parsed in your browser and drawn as the graph a crawler builds from it. Every nested object is a node and the property that holds it is the edge. Tap a node to inspect its properties, or drag to rearrange.

Why Conditional Logic Is Better Than Static Templates

  • Pulls the claim summary, verdict, and claim source from the same editorial fields that render the article, so markup and visible verdict cannot disagree.
  • Validates the rating scale in code, so a CMS default of 0 for worstRating never ships.
  • Omits the numeric scale entirely when the newsroom uses text-only verdicts, instead of inventing numbers.
  • Gives one switch point if you later stop emitting ClaimReview as the phase-out completes.

Property Reference

What Google's Fact check documentation requires and recommends, property by property. These are the same rules the SchemaCDN validator checks. Each name links to its schema.org definition.

Google Search no longer shows fact check rich results, but Fact Check Explorer still reads ClaimReview markup, so these properties still apply there.

Fact check properties in Google's documentation
PropertyGoogleExpectsNotes
claimReviewedRequiredTextA short summary of the claim being evaluated. Up to 75 characters.
reviewRatingRequiredRatingThe assessment of the claim. This object supports both a numeric and a textual assessment.
reviewRating.alternateNameRequiredTextThe truthfulness rating assigned to ClaimReview.reviewRating, as a human-readable short word or phrase. The textual value is currently the only value shown in search results.
reviewRating.bestRatingRecommendedNumberFor numeric ratings, the best value possible in the scale from worst to best.
reviewRating.nameRecommendedTextSame as alternateName, and used when alternateName is not provided.
reviewRating.ratingValueRecommendedNumberA numeric rating of this claim, in the range worstRating to bestRating inclusive.
reviewRating.worstRatingRecommendedNumberFor numeric ratings, the worst value possible in a scale from worst to best.
urlRequiredURLLink to the page hosting the full article of the fact check.
authorRecommendedOrganization or PersonThe publisher of the fact check article, not the publisher of the claim.
author.nameRecommendedTextName of the organization that is publishing the fact check.
author.urlRecommendedURLThe URL of the publisher of the fact check. This can be a home page, contact page, or other appropriate page.
itemReviewedRecommendedClaimAn object describing the claim being made.
itemReviewed.appearanceRecommendedURL or CreativeWork, can repeatA link to, or inline description of, a CreativeWork in which this claim appears.
itemReviewed.authorRecommendedOrganization or PersonThe author of the claim, not the author of the fact check.
itemReviewed.datePublishedRecommendedDateTime or DateThe date when the claim was made or entered public discourse.
itemReviewed.firstAppearanceRecommendedURL or CreativeWorkA link to, or inline description of, a CreativeWork in which this specific claim first appears.

Explore Other Schema Framework Pages

Retired Home Activities Use for virtual classes and activities where participation details and timing are clearly listed. Event Open Retired How-To Use for instructional content that teaches a process through ordered steps and actionable detail. HowTo Open Image Metadata Use on image pages and image hosts that expose ownership and licensing information to search engines. ImageObject Open Job Posting Use for active job listings that include role details, hiring entity, and location/salary context. JobPosting Open Retired Learning Video Use for educational videos where the learning objective and pedagogical structure are explicit. LearningResource Open Local Business Use for physical businesses serving local customers with publicly verifiable contact and location details. LocalBusiness Open Loyalty Program Use to publish a loyalty program and its tiers once at the organization level, so member prices and member shipping can reference them. MemberProgram Open Math Solvers Use for pages that solve mathematical expressions and present step-by-step computational guidance. MathSolver Open Merchant Listing Use on pages where a product can be bought, with price, availability, shipping and return details. Product Open Limited Movie Use for movie detail pages with canonical film information and transparent metadata attribution. Movie Open Organization Use for official organization pages to clarify brand identity and authoritative entity signals. Organization Open Retired Practice Problems Use for educational practice content that presents solvable problems and answer validation structure. Quiz Open Product Snippet Use for product pages where pricing, availability, and product identity are visible to users. Product Open Product Variants Use when one product comes in variants such as size or color, grouped with ProductGroup. ProductGroup Open Profile Page Use for creator or contributor profile pages where identity attributes and ownership are explicit. ProfilePage Open Q&A Use for pages where users submit questions and community or editorial answers are displayed. QAPage Open Recipe Use for recipe pages with complete ingredients, instructions, and preparation details. Recipe Open Return Policy Use to publish a merchant return policy once at the organization level, with offer-level overrides. MerchantReturnPolicy Open Review Snippet Use when a page publishes genuine reviews tied to a clearly identified product, service, or entity. Review Open Shipping Policy Use to publish shipping rates, delivery times and destinations once at the organization level. ShippingService Open Site Name Use on the home page so Google shows the preferred site name in search results. WebSite Open Retired Sitelinks Search Box Use on sites with a functioning internal search endpoint that can accept URL query parameters. WebSite Open Software App (Beta) Use for software product pages that describe platform support and application category clearly. SoftwareApplication Open Limited Speakable Use for news-style pages where specific text segments are appropriate for text-to-speech playback. SpeakableSpecification Open Subscription and Paywalled Content Use for pages with restricted sections so Google can distinguish free previews from protected content. CreativeWork Open Limited Vacation Rental Use for rental property detail pages where booking-relevant amenities and location signals are explicit. VacationRental Open Retired Vehicle Listing Use for inventory pages selling vehicles with standardized listing fields and offer information. Car Open Video Use for pages where a primary video is embedded and key media metadata is visible on-page. VideoObject Open Article Use for editorial pages where the visible content is a complete article with a clear byline and publication timestamps. Article Open Limited Book Actions Use when your page helps users read, preview, or purchase books through clearly described actions. Book Open Breadcrumb Use on pages that belong to a clear hierarchy and display navigational trail links users can follow. BreadcrumbList Open Carousel Use when a page lists multiple related entities in a scannable sequence that can be surfaced as cards. ItemList Open Course Use for educational offerings where curriculum details, provider identity, and delivery context are explicit. Course Open Dataset Use for dataset landing pages so datasets are discoverable in Google Dataset Search with license, creator and download details. Dataset Open Discussion Forum Use for forum and community threads where a primary post and subsequent replies are publicly visible. DiscussionForumPosting Open Limited Education Q&A Use for educational question-answer pages where a single canonical answer and supporting context are visible. Quiz Open Employer Aggregate Rating Use on pages that publish employer rating aggregates from a clear and policy-compliant review source. EmployerAggregateRating Open Retired Estimated Salary Use for compensation insight pages that present transparent salary ranges for specific occupations and locations. Occupation Open Event Use for upcoming events with a real-world or virtual occurrence, schedule, and location context. Event Open

Implement Fact Check Schema Frameworks Correctly

Get implementation support for conditional schema architecture, validation, and deployment governance.