DEV Community

Ahmed Niazy
Ahmed Niazy

Posted on

A Deep Dive Into Schema.org Structured Data For SEO

This article explains a reusable structured data module.
It is typically implemented as a composable or utility.
It is usually written in TypeScript.
It exports a factory function.
That factory returns multiple helper functions.
Each helper function builds a Schema.org JSON LD object.
These objects are meant to be embedded in the page HTML.
Typically you embed them inside a script tag.
The script tag type should be application/ld+json.
Search engines read that JSON LD.
They use it to understand your pages.
They may produce rich results.
They may improve entity understanding.
They may improve crawl interpretation.

Important note

This composable only generates plain JavaScript objects.
It does not inject them into head by itself.
You still need to connect the output to your head management.
In most frameworks, you can do that via your head management system.
Or you can use a dedicated structured data integration.
The composable focuses on generation logic.

What this file contains

The file contains TypeScript interfaces.
Each interface defines the input shape for a generator.
Then the file defines the schema module.
Inside the schema module there are shared dependencies.
There is a route reference.
There is a locale reference.
There is a configuration reference.
Then there is baseUrl.
baseUrl comes from your configuration.
If baseUrl is missing, it falls back to a default domain.

After that, the file defines many generator functions.
All of them return a schema object.
Most return an object unconditionally.
One generator returns null when there is no data.
That generator is the FAQ schema generator.

How to use outputs in SEO

Search engines do not rank pages just because JSON LD exists.
But JSON LD helps them understand.
Better understanding can lead to better presentation.
Better presentation can lead to better click through.
Rich results can add extra screen space.
Extra screen space can increase trust.
It can also reduce ambiguity.

Structured data can help with

  • Entity disambiguation
  • Site identity
  • Publisher identity
  • Breadcrumb display
  • FAQ rich results
  • Job posting rich results
  • Product like availability signals for services
  • App rich results for SoftwareApplication

The exact rich result eligibility depends on search engine rules.
But the shapes used here are aligned with common Schema.org patterns.

Shared dependencies inside the schema module

The module reads the current route.
It reads the current locale.
It reads baseUrl.
These three values are used by helper methods.
The schema generators themselves accept explicit URLs.
So they are reusable across pages.

The helper methods focus on

  • Getting the current page URL in a consistent way
  • Building breadcrumb items from the route path

Now we will go function by function.

Organization schema

Generator

Organization schema generator

Goal

This function generates a Schema.org Organization entity.
An Organization is often used as the publisher.
It can also represent your brand entity.
It can connect your website to social profiles.
It can add contact and address info.
It can help build a knowledge graph entity.

Input interface

OrganizationSchemaOptions has these fields

Required

  • name
  • url
  • logo

Optional

  • alternateName
  • description
  • founder
  • foundingDate
  • foundingLocation
  • telephone
  • email
  • address
  • contactPoint
  • sameAs

Output shape

The base object includes

Then it conditionally adds optional fields.
It only adds a field if you provided it.
This prevents empty fields.
That is helpful for clean output.

Address field

If address exists, it builds a PostalAddress object.
It sets [at]type to PostalAddress.
Then it spreads the address fields.
Those fields are

  • streetAddress
  • addressLocality
  • addressRegion
  • postalCode
  • addressCountry

ContactPoint field

If contactPoint exists and is not empty, it maps each entry.
Each entry becomes a ContactPoint object.
It sets [at]type to ContactPoint.
Then it spreads the input.
This can represent sales, support, or other contact types.

sameAs field

If sameAs exists and is not empty, it adds sameAs.
sameAs is a list of URLs.
Common examples are

  • Facebook page URL
  • Instagram profile URL
  • LinkedIn company page URL
  • X profile URL
  • YouTube channel URL

SEO value of Organization schema

  • It defines who owns the site.
  • It defines your brand name and logo.
  • It can connect your brand to social profiles.
  • It helps search engines connect content to a publisher.
  • It can reduce ambiguity when your brand name is generic.
  • It can help create a consistent entity graph.

WebPage schema

Generator

WebPage schema generator

Goal

This function describes a single web page.
It supports core page metadata.
It can connect the page to a website.
It can connect the page to a publisher.
It can attach a mainEntity.

Input interface

WebPageSchemaOptions

Required

  • url
  • name
  • description
  • inLanguage

Optional

  • isPartOf
  • publisher
  • mainEntity
  • datePublished
  • dateModified

Output shape

The base object includes

isPartOf field

If isPartOf exists, it builds a Website object.
It sets [at]type to Website.
Then it adds url and name.
This connects a page to a website entity.

publisher field

If publisher exists, it builds an Organization object.
It sets [at]type to Organization.
It sets name.
It sets logo as an ImageObject.
The logo ImageObject has

  • [at]type ImageObject
  • url

mainEntity field

If mainEntity exists, it attaches it as is.
The type is Record.
This means you can pass any schema object.
For example, you can pass a RealEstateAgent.
Or you can pass an Article.
Or you can pass a FAQPage.
This is flexible.
But it also means you need to validate your own mainEntity.

datePublished and dateModified

If provided, they are added directly.
They should be ISO 8601 date strings.
Examples

  • 2026-02-03
  • 2026-02-03T10:00:00Z

SEO value of WebPage schema

  • It clarifies the canonical page identity.
  • It clarifies language.
  • It can connect to a website and publisher.
  • It can connect to a main entity.
  • It can help search engines interpret page intent.

BreadcrumbList schema

Generator

BreadcrumbList schema generator

Goal

BreadcrumbList helps search engines understand hierarchy.
It may show breadcrumb rich results.
It can also help with sitelinks context.

Input interface

BreadcrumbSchemaOptions

  • items is an array of name and item URL.

Output shape

The output includes

  • [at]context https://schema.org
  • [at]type BreadcrumbList
  • itemListElement as an array of ListItem

Each ListItem includes

  • [at]type ListItem
  • position starting at 1
  • name
  • item

SEO value of BreadcrumbList

  • It clarifies the user journey.
  • It clarifies category and page relationships.
  • It can appear in SERP snippets.
  • It can reduce URL clutter in results.

RealEstateAgent schema

Generator

RealEstateAgent schema generator

Goal

This function describes a RealEstateAgent entity.
This is relevant for a real estate platform.
It can be used for company pages or agent profiles.

Input interface

RealEstateAgentSchemaOptions

Required

  • name
  • url

Optional

  • image
  • telephone
  • email
  • priceRange
  • address
  • geo
  • openingHoursSpecification
  • sameAs
  • areaServed

Output shape

Base object

  • [at]context https://schema.org
  • [at]type RealEstateAgent
  • name
  • [at]id equals options.url
  • url equals options.url

This is a common pattern.
Using [at]id can help connect entities.

image field

If image exists, it is added directly.
You should provide an absolute URL.

telephone and email

If present, they are added as strings.

priceRange

If present, it is added.
It is usually a string like

  • $$
  • $1000 to $5000

address

If present, it becomes a PostalAddress.
Same structure as the Organization address.

geo

If present, it becomes GeoCoordinates.
It sets

  • [at]type GeoCoordinates
  • latitude
  • longitude

openingHoursSpecification

If present and non empty, each item becomes OpeningHoursSpecification.
It sets [at]type OpeningHoursSpecification.
Then it spreads the input fields.
Those include

  • dayOfWeek as an array of strings
  • opens
  • closes

sameAs

If present, it is added as a list of URLs.

areaServed

If present, it becomes a City.
It sets [at]type City.
It sets name.

SEO value of RealEstateAgent schema

  • It defines an entity that can be referenced.
  • It can support local intent signals.
  • It can connect contact details and location.
  • It can help clarify the business type.

LocalBusiness schema

Generator

LocalBusiness schema generator

Goal

This function describes a LocalBusiness entity.
This is a generic business listing schema.
It can represent branches or offices.

Input interface

LocalBusinessSchemaOptions

Required

  • name
  • url

Optional

  • image
  • telephone
  • priceRange
  • address
  • geo
  • openingHoursSpecification
  • sameAs

Output shape

Base object

Optional fields are handled similarly to RealEstateAgent.

SEO value of LocalBusiness schema

  • It supports local SEO context.
  • It provides address and geo coordinates.
  • It can support knowledge panel consistency.
  • It can connect opening hours.

Service schema

Generator

Service schema generator

Goal

This function describes a Service.
A Service schema can represent what you offer.
It can connect a service type to a provider.
It can attach offers.

Input interface

ServiceSchemaOptions

Required

  • serviceType
  • provider

Optional

  • areaServed
  • description
  • offers

Provider object

provider has

  • name
  • url
  • logo
  • sameAs optional

Output shape

Base object

Provider is set to

  • [at]type Organization
  • name
  • url
  • logo

Provider sameAs

If provider.sameAs exists and is non empty, it is attached.
This uses a type cast to edit schema.provider.

areaServed

If present, it becomes a Place.
It sets

  • [at]type Place
  • name

description

If present, it is added.

offers

If offers exists, it creates an Offer object.
It sets [at]type Offer.
Then it spreads all fields from offers.

Offer fields can include

  • url
  • priceCurrency
  • price
  • priceSpecification
  • availability

priceSpecification

If priceSpecification exists, it becomes a PriceSpecification object.
It sets [at]type PriceSpecification.
Then it spreads the priceSpecification fields.
Those fields can include

  • price
  • priceCurrency
  • validFrom

SEO value of Service schema

  • It clarifies what you do.
  • It can connect a service to the provider entity.
  • It can expose offer like details.
  • It can support better matching to intent.

BlogPosting schema

Generator

BlogPosting schema generator

Goal

This function builds BlogPosting structured data.
It is used for blog content.
It can help eligibility for article rich results.
It can help publishers clarify authorship.

Input interface

BlogPostingSchemaOptions

Required

  • mainEntityOfPage.url
  • headline
  • author.name
  • publisher.name
  • publisher.logo
  • datePublished

Optional

  • description
  • image
  • author.url
  • dateModified

Output shape

Base object includes

  • [at]context https://schema.org
  • [at]type BlogPosting
  • mainEntityOfPage as WebPage with [at]id set to URL
  • headline
  • author as Person with name
  • publisher as Organization with name and logo ImageObject
  • datePublished

Conditional fields

If description exists, it is added.
If image exists, it is added.
If author.url exists, author.url is attached.
If dateModified exists, dateModified is attached.

SEO value of BlogPosting schema

  • It clarifies that content is a blog post.
  • It clarifies author and publisher.
  • It provides publish and modified dates.
  • It helps search engines understand content freshness.

Article schema

Generator

Article schema generator

Goal

This function builds Article structured data.
It is similar to BlogPosting.
It is useful for editorial content and guides.

Input interface

ArticleSchemaOptions

Required

  • mainEntityOfPage.url
  • headline
  • author.name
  • publisher.name
  • publisher.logo
  • datePublished

Optional

  • description
  • image string or string array
  • author.url
  • dateModified
  • keywords

Output shape

Base object includes

  • [at]context https://schema.org
  • [at]type Article
  • mainEntityOfPage WebPage with [at]id
  • headline
  • author Person
  • publisher Organization and ImageObject logo
  • datePublished

Image handling

If image exists, it ensures schema.image is an array.
If the input is already an array, it uses it.
If the input is a string, it wraps it as a single element array.
This is convenient for consumers.

keywords

If keywords exists, it is added.
This is a plain string in this implementation.
Sometimes keywords is provided as comma separated.

SEO value of Article schema

  • It clarifies content type as an article.
  • It improves author and publisher clarity.
  • It can help with article rich results.
  • It supports date signals.

SoftwareApplication schema

Generator

SoftwareApplication schema generator

Goal

This function describes a software application.
This is appropriate for a SaaS platform.
It can help search engines understand your product.
It can connect offers and ratings.

Input interface

SoftwareApplicationSchemaOptions

Required

  • name
  • applicationCategory
  • description
  • url
  • author.name
  • author.url

Optional

  • operatingSystem
  • image
  • offers
  • aggregateRating
  • applicationSubCategory
  • softwareVersion

Output shape

Base object includes

  • [at]context https://schema.org
  • [at]type SoftwareApplication
  • name
  • applicationCategory
  • description
  • url
  • author as Organization with name and url

operatingSystem

If present, it is attached.
For web apps, you might use Web.
For native apps, you might use iOS or Android.

image

If present, it is attached.
Provide an absolute URL.

offers

If offers exists, it builds an Offer object.
Offer includes

  • [at]type Offer
  • price
  • priceCurrency
  • availability
  • url optional

aggregateRating

If present, it becomes AggregateRating.
It sets

  • [at]type AggregateRating
  • ratingValue
  • ratingCount

applicationSubCategory and softwareVersion

If present, they are attached.
These can help describe versions and sub type.

SEO value of SoftwareApplication schema

  • It clarifies your product as software.
  • It can display pricing and availability.
  • It can support rating snippets depending on policy.
  • It helps search engines understand app category.

JobPosting schema

Generator

JobPosting schema generator

Goal

This function describes a job listing.
JobPosting can enable job rich results.
It can help distribute your job posts.

Input interface

JobPostingSchemaOptions

Required

  • title
  • description
  • datePosted
  • validThrough
  • employmentType
  • hiringOrganization.name

Optional

  • identifier
  • hiringOrganization.sameAs
  • hiringOrganization.logo
  • jobLocation
  • remote
  • applicantLocationRequirements
  • baseSalary
  • responsibilities
  • qualifications
  • skills
  • educationRequirements
  • experienceRequirements
  • incentiveCompensation
  • industry
  • jobBenefits

Output shape

Base object includes

  • [at]context https://schema.org/
  • [at]type JobPosting
  • title
  • description
  • datePosted
  • validThrough
  • employmentType
  • hiringOrganization as Organization

identifier

If identifier exists, it becomes PropertyValue.
It sets

  • [at]type PropertyValue
  • name
  • value

hiringOrganization fields

If sameAs exists, it is attached.
If logo exists, it is attached.

jobLocation

If jobLocation exists, it becomes Place with PostalAddress.

remote

If remote is provided, it sets schema.remote to a string.
It uses options.remote.toString.
This results in true or false as strings.
Some consumers expect a boolean.
But this is the current behavior.
If you depend on strict schema validation, review this.

applicantLocationRequirements

If provided, it becomes a Country object with name.

baseSalary

If provided, it builds MonetaryAmount.
It sets

  • [at]type MonetaryAmount
  • currency
  • value as QuantitativeValue

QuantitativeValue includes

  • [at]type QuantitativeValue
  • unitText
  • minValue optional
  • maxValue optional

Responsibilities and other text fields

If provided, they are attached as strings.
This includes responsibilities, qualifications, skills, and more.

SEO value of JobPosting schema

  • It can enable job rich results.
  • It improves job distribution.
  • It clarifies salary and location.
  • It clarifies employer identity.

FAQPage schema

Generator

FAQPage schema generator

Goal

This function creates FAQPage structured data.
FAQ structured data can produce FAQ rich results.
It is often used on landing pages.
It can also be used on documentation pages.

Input interface

FAQSchemaOptions

  • items is an array of question and answer.

Behavior for empty data

If items is missing or empty, the function returns null.
This is important.
It prevents injecting an empty FAQPage.
It also avoids invalid schema.

Output shape

Each item becomes

  • [at]type Question
  • name set to the question
  • acceptedAnswer as Answer
  • acceptedAnswer.text set to the answer

SEO value of FAQPage schema

  • It answers common questions directly.
  • It can expand SERP snippets.
  • It can increase click through when implemented correctly.
  • It can improve relevance understanding.

Helper Current page URL builder

Goal

This helper builds the current page absolute URL.
It uses the route path.
It ensures language prefix is consistent.
It removes locale segments from the route.

Logic

  • path is route.path
  • langPrefix is /en when locale is en
  • otherwise langPrefix is empty
  • cleanPath removes a leading /en or /ar
  • if the route becomes empty, it uses /
  • it returns baseUrl + langPrefix + cleanPath

Why this matters for SEO

Absolute URLs are preferred inside schema.
A consistent URL reduces duplicate entity identities.
Locale paths can cause duplicates if not handled.
This helper ensures a stable, localized URL.

Helper Breadcrumb builder from route

Goal

This helper generates breadcrumb items automatically.
It uses route.path.
It splits the path into segments.
It skips locale segments.
It builds cumulative URLs.
It generates readable names.

Output

It returns an array of

  • name
  • item

The first breadcrumb is always Home.
If locale is ar, it uses العربية.
If locale is not ar, it uses Home.
The Home item is baseUrl + /.

Name generation details

For each non locale segment

  • it splits by hyphen
  • it capitalizes the first letter of each word
  • it joins with space

So a segment like property-management becomes
Property Management

URL generation details

It builds currentPath incrementally.
It uses langPrefix based on locale.
It builds fullPath as baseUrl + langPrefix + currentPath.

Then it pushes { name, item }.

SEO value of auto breadcrumbs

Even if you render breadcrumbs in UI, schema breadcrumbs help crawlers.
They provide a machine readable hierarchy.
They can reduce ambiguity on nested routes.
They can improve display snippets.

Integration guidance

The composable returns generator functions.
A typical usage pattern is

  • Build schema objects based on page data
  • Serialize them to JSON
  • Inject into head as JSON LD

Example high level approach

  • For a homepage
    • Organization
    • WebPage
    • BreadcrumbList with just Home
    • Service or LocalBusiness as mainEntity
  • For a blog post page
    • BlogPosting
    • WebPage with mainEntity set to BlogPosting
    • BreadcrumbList
  • For a guide page
    • Article
    • WebPage with mainEntity set to Article
  • For a FAQ landing page
    • FAQPage
    • WebPage with mainEntity set to FAQPage
  • For careers
    • JobPosting
    • WebPage with mainEntity set to JobPosting

Data quality checklist

Use absolute URLs everywhere.
Make sure baseUrl matches your production domain.
Make sure routes generate canonical paths.
Use consistent trailing slash rules.
Do not generate multiple conflicting schemas for the same entity.
Use [at]id consistently when you want to connect entities.
Make sure date strings are valid ISO 8601.
Make sure images are accessible and indexable.
Make sure logos are high quality and stable.
Provide sameAs links that are official.
Avoid placeholder values.
Avoid empty arrays.
Avoid injecting null schema.

Common mistakes and how this file avoids them

It only adds optional fields when they exist.
It maps arrays only when they have length.
It wraps Article image into an array.
It returns null for empty FAQ items.
It sets context and type explicitly.
It uses stable baseUrl.

Potential improvements you may consider

The JobPosting remote field is a string.
Some schema validators might expect a boolean or a different field.
If you see validation warnings, adjust accordingly.

The Organization founder field is a string.
Schema.org often allows Person or Organization.
If you need richer founder data, model it as a Person object.

The composable does not implement WebSite schema.
It uses Website type inside isPartOf.
If you want a full WebSite schema, add a generator.

The composable does not implement WebSite SearchAction.
If you have a site search, you can add it for sitelinks search box.

Testing structured data

After you inject JSON LD, test the page.
Use a structured data testing tool.
Validate that required fields exist.
Validate that URLs resolve.
Validate that language matches content.
Validate that breadcrumbs match navigation.
Validate that FAQ matches visible content.

Final summary

This module is a structured data factory.
It centralizes Schema.org JSON LD generation.
It supports multiple content types.
It supports localization aware URL helpers.
It supports breadcrumb automation.
Its SEO value comes from clarity.
Clarity supports richer understanding.
Richer understanding supports better presentation.

Appendix A Field by field quick reference

Organization

[at]context
[at]type
name
url
logo
alternateName
description
founder
foundingDate
foundingLocation
telephone
email
address PostalAddress
contactPoint ContactPoint array
sameAs array

WebPage

[at]context
[at]type
url
name
description
inLanguage
isPartOf Website
publisher Organization with logo ImageObject
mainEntity any schema object
datePublished
dateModified

BreadcrumbList

[at]context
[at]type
itemListElement ListItem array
ListItem position
ListItem name
ListItem item

RealEstateAgent

[at]context
[at]type
name
[at]id
url
image
telephone
email
priceRange
address PostalAddress
geo GeoCoordinates
openingHoursSpecification array
sameAs array
areaServed City

LocalBusiness

[at]context
[at]type
name
[at]id
url
image
telephone
priceRange
address PostalAddress
geo GeoCoordinates
openingHoursSpecification array
sameAs array

Service

[at]context
[at]type
serviceType
provider Organization
provider sameAs
areaServed Place
description
offers Offer
offers priceSpecification PriceSpecification

BlogPosting

[at]context
[at]type
mainEntityOfPage WebPage [at]id
headline
description
image
author Person name and url optional
publisher Organization with logo ImageObject
datePublished
dateModified

Article

[at]context
[at]type
mainEntityOfPage WebPage [at]id
headline
description
image array
author Person
publisher Organization with logo ImageObject
datePublished
dateModified
keywords

SoftwareApplication

[at]context
[at]type
name
applicationCategory
applicationSubCategory
description
url
operatingSystem
image
author Organization
offers Offer
aggregateRating AggregateRating
softwareVersion

JobPosting

[at]context
[at]type
title
description
identifier PropertyValue
datePosted
validThrough
employmentType
hiringOrganization Organization
jobLocation Place with PostalAddress
remote string
applicantLocationRequirements Country
baseSalary MonetaryAmount with QuantitativeValue
responsibilities
qualifications
skills
educationRequirements
experienceRequirements
incentiveCompensation
industry
jobBenefits

FAQPage

[at]context
[at]type
mainEntity Question array
Question name
acceptedAnswer Answer
Answer text

Appendix B Practical injection pattern

1 Generate the schema object.
2 JSON stringify it.
3 Inject it into a script tag in the page head.
4 Ensure the schema matches what users see.
5 Validate.
6 Monitor search console for enhancements.

Top comments (0)