How-To Schema Framework

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

  • Google no longer shows How-to rich results: they were limited to desktop on Aug 8, 2023 and removed from desktop on Sep 13, 2023, when Google deprecated the result type. Search appearance report and Rich Results Test support ended within 30 days.
  • HowTo is still valid schema.org: it describes ordered steps, tools, supplies and duration for AI assistants and other structured data consumers.
  • Keep it only where a page really is a step-by-step guide with visible steps, and expect no rich result. Do not add it to pages to chase a Search feature.

When To Use It

Google Search Central RetiredDocumentation changelog

The documentation page has been removed and its URL now redirects to the Search Central updates changelog. Use HowTo markup only on instructional pages whose steps are visible, for schema.org semantics rather than a Google feature.

Key Implementation Documentation Highlights

  • Google lists no required properties: the How-to documentation is gone and the feature is retired.
  • Google lists no recommended properties either. The framework below follows schema.org: name, step (HowToStep with text, plus optional name, url and image), totalTime, supply, tool, image and description.
  • Write totalTime as an ISO 8601 duration such as PT25M or PT1H30M.
  • General structured data policies still apply: mark up only content visible on the page and keep the page indexable.
  • The Rich Results Test no longer reports How-to; use the Schema Markup Validator to check syntax.

Rules the framework enforces before it emits markup:

  • Steps not visible on the page, or a noindex or canonicalized URL: emit nothing.
  • No name, no steps, or a step without text: emit nothing rather than a partial guide.
  • totalTime must be a valid ISO 8601 duration; whole minutes are converted, anything else is dropped.
  • Step url values are #fragment links on the page itself, and image URLs must be absolute.

Template Approach

const pageData = {
  title: "How to replace a bike chain",
  totalTime: "PT25M",
  steps: [
    "Measure the old chain with a chain checker.",
    "Open the quick link and remove the old chain.",
    "Fit the new chain and close the quick link."
  ]
};

const staticTemplate = {
  "@context": "https://schema.org",
  "@type": "HowTo",
  "name": pageData.title,
  "totalTime": pageData.totalTime,
  "step": pageData.steps.map((text) => ({ "@type": "HowToStep", "text": text }))
};

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_DURATION = /^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/;

function toIsoDuration(value) {
  // accepts an ISO 8601 duration string or a whole number of minutes
  if (typeof value === "string") return ISO_DURATION.test(value.trim()) ? value.trim() : null;
  if (!Number.isInteger(value) || value <= 0) return null;
  const hours = Math.floor(value / 60);
  const minutes = value % 60;
  return "PT" + (hours ? hours + "H" : "") + (minutes ? minutes + "M" : "");
}

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 buildStep(step, index, pageUrl) {
  const text = (step.text || "").trim();
  if (!text) return null;
  return {
    "@type": "HowToStep",
    "position": index + 1,
    "name": step.name,
    "text": text,
    "url": step.anchor ? pageUrl + "#" + step.anchor : null,
    "image": isAbsoluteUrl(step.image) ? step.image : null
  };
}

function buildHowToSchema(source) {
  // Google retired How-to rich results in Sep 2023: no rich result, no Google required properties.
  // Emit only when the steps are visible on the page, for schema.org semantics 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.stepsVisible !== true) return null;

  const name = (source.title || "").trim();
  const steps = (source.steps || []).map((s, i) => buildStep(s, i, source.url));
  if (!name || !steps.length || steps.includes(null)) return null;

  const schema = {
    "@context": "https://schema.org",
    "@type": "HowTo",
    "name": name,
    "description": source.description,
    "image": isAbsoluteUrl(source.image) ? source.image : null,
    "totalTime": toIsoDuration(source.totalMinutes),
    "supply": (source.supplies || []).map((s) => ({ "@type": "HowToSupply", "name": s })),
    "tool": (source.tools || []).map((t) => ({ "@type": "HowToTool", "name": t })),
    "step": steps
  };

  return compact(schema);
}

// Usage:
// buildHowToSchema({
//   url: "https://www.example.com/guides/replace-bike-chain",
//   canonicalUrl: "https://www.example.com/guides/replace-bike-chain",
//   indexable: true,
//   stepsVisible: true,
//   title: "How to replace a bike chain",
//   description: "Swap a worn 11-speed chain with a chain tool and a quick link.",
//   image: "https://www.example.com/guides/replace-bike-chain/hero.jpg",
//   totalMinutes: 25,
//   supplies: ["11-speed chain", "Quick link"],
//   tools: ["Chain tool", "Chain checker"],
//   steps: [
//     { name: "Check wear", text: "Measure the old chain with a chain checker; replace it at 0.5% stretch.", anchor: "step-1" },
//     { name: "Remove the old chain", text: "Open the quick link or push out a pin with the chain tool.", anchor: "step-2" },
//     { name: "Size and fit the new chain", text: "Match the old chain length, thread it through the derailleur and close the quick link.", anchor: "step-3", image: "https://www.example.com/guides/replace-bike-chain/quick-link.jpg" }
//   ]
// });

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

  • Builds steps from the same ordered records that render the guide, so markup and visible steps stay in sync.
  • Converts stored minutes to ISO 8601 durations instead of trusting free text such as 25 mins.
  • Drops supplies, tools and images that the content model lacks, instead of emitting empty arrays.
  • Keeps HowTo behind one builder, so removing it later is a single change.

Property Reference

Google retired the How-To rich result, so its documentation no longer lists required or recommended properties. The framework above is still valid schema.org markup and still describes the page to search engines and AI assistants.

Schema.org types used

Explore Other Schema Framework Pages

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 Retired Fact Check Use for fact-checking pages that evaluate a specific claim with a transparent rating methodology. ClaimReview Open Retired Home Activities Use for virtual classes and activities where participation details and timing are clearly listed. Event Open

Implement How-To Schema Frameworks Correctly

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