Open-source project
spatie/schema-org avatar
spatie/schema-org

spatie/schema-org: Fluent Schema.org Types and ld+json

A fluent builder Schema.org types and ld+json generator

1,508 stars146 forksPHPMIT

At a glance

What is it?
spatie/schema-org is a PHP package for constructing Schema.org objects through a fluent API and rendering them as JSON-LD. It suits PHP applications that need typed structured-data objects without manually assembling every property and nested relationship.
Who is it for?
Adopt spatie/schema-org when a PHP application needs to create Schema.org JSON-LD through typed objects and fluent calls, especially when nested entities or multiple graph items are involved. Do not treat it as a validator or a replacement for checking search-engine requirements.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What spatie/schema-org Solves in PHP Structured Data

spatie/schema-org addresses the repetitive work involved in creating Schema.org markup by hand. A PHP application can create a type such as LocalBusiness, Product, Organization, or Book, assign supported properties through named methods, and serialize the result as JSON-LD. The target audience is PHP developers who publish pages containing products, businesses, articles, events, people, and other entities that search engines can interpret through structured data.

The package covers the core Schema.org vocabulary rather than a small set of hand-written schemas. According to the README, the classes and methods in src are generated from Schema.org's JSON-LD standards file. This matters because the generated API is intended to follow the vocabulary as a whole, while still presenting it through a PHP object model. The package does not decide whether a page qualifies for a particular search feature, and it does not validate application content against search-engine policies. It produces structured markup and leaves validation to external checks.

The package also provides direct access to properties that may not have convenient domain-specific methods. That is useful for uncommon Schema.org properties, but it also means that developers can bypass type checking with setProperty. The central design choice is therefore convenience at the vocabulary level, not enforcement of business validity.

Typed Objects, Nested Relationships, and JSON-LD Output

The package uses the Schema factory class to create supported types. Each type exposes methods corresponding to Schema.org properties, and property values can include nested schema objects. In the README example, a LocalBusiness receives a name, an email, and a ContactPoint through its contactPoint property; the ContactPoint has areaServed set to Worldwide. Serialization adds the JSON-LD context and type, then emits the object in a script element through toScript.

The package supports two construction styles. Schema::localBusiness()->name('Spatie') is the fluent factory form, while new LocalBusiness() followed by ->name('Spatie') is equivalent for types imported into the application. Types also implement SPL's ArrayAccess, so a property can be checked, assigned, read, or removed with array notation. This gives an application a choice between explicit property methods and direct property access.

For conditional application data, the if method can keep a long fluent chain intact. The callback receives the schema object, allowing a property to be added only when the source array contains the corresponding value. This is useful when CMS or form data varies, although the callback still leaves the developer responsible for deciding which properties are required.

Output methods include toArray, toScript, and plain JSON encoding through json_encode. An object can also be echoed directly because the README states that its output is the same as toScript(). The identifier behavior follows JSON-LD conventions: simple string identifiers use the @id key rather than identifier.

Installing spatie/schema-org and Creating the First ld+json Script

The README gives one Composer installation command. It does not document a separate initialization command or a required configuration file. After installation, the first use is to import Schema and create a type. The example below builds a LocalBusiness with nested contact information and renders it as a script.

The command installs the package through Composer:

bash
composer require spatie/schema-org

The README then shows this PHP object and its rendered result:

php
use Spatie\SchemaOrg\Schema;

$localBusiness = Schema::localBusiness()
    ->name('Spatie')
    ->email('[email protected]')
    ->contactPoint(Schema::contactPoint()->areaServed('Worldwide'));

echo $localBusiness->toScript();

The rendered output includes the application/ld+json script type, the https://schema.org context, the LocalBusiness type, and the nested ContactPoint object. The README also gives the equivalent HTML form of the script output. A developer should confirm that the resulting JSON is embedded once, in the correct page location, and that the values match the visible page content.

For a first application use, call toArray when the surrounding template needs an array, or call toScript when the template needs a complete script tag. The README does not document framework-specific integration, so Blade, Symfony, Laravel, or other template integration must be handled by the application.

Schema.org Version Coverage and Custom Property Escape Hatches

The README states that the code in src is generated from Schema.org's JSON-LD standards file, identified as release 13.0 in the linked source. The package consequently offers objects and methods for the entire core vocabulary represented by that generated source. This gives developers a broad typed surface, but it also creates a version boundary. A newer Schema.org property may not have a named method until the generated source is updated.

For properties that need direct handling, setProperty('foo', 'bar') adds a custom property to an object. This is a deliberate escape hatch rather than evidence that every arbitrary key is part of the package's typed vocabulary. Existing values can be read with getProperty, and a default can be supplied when a property is absent. getProperties returns the complete property collection, while addProperties accepts a property map in one call.

Enumeration child types are represented as classes with constants. The README example uses BookFormatType::Hardcover for a bookFormat property. This keeps enum values named in PHP instead of requiring every caller to repeat a raw string.

The generated vocabulary coverage should be checked before relying on a property in a new application. The README does not describe a compatibility table, migration policy, or runtime check for vocabulary revisions. The package's API coverage and the Schema.org version accepted by downstream consumers are separate concerns.

Graph Support for Shared Organizations, Products, and Other Entities

The package includes a Graph abstraction for representing multiple schema items that relate to one another. The README describes Graph methods and utilities for creating items and reusing an existing instance. Its example creates a product, links the product to an organization, and hides the organization from the created script tag while another part of the application fills in the organization.

This graph-oriented model is more useful than emitting unrelated script tags when entities share references. A product can point to an Organization, and the graph can preserve the relationship while allowing the organization to be completed later. The hide method controls whether a selected class is included directly in the generated script. That distinction matters when a graph contains an entity that is referenced but should not be rendered as a separate visible node.

The README's graph example is truncated, so the complete output format and all graph options are not documented there. Developers should not infer support for graph serialization details that are not shown. The documented parts establish a mechanism for shared or related objects, not a complete policy for graph identifiers, references, or nested contexts.

Compared with manually writing a JSON-LD @graph object, spatie/schema-org offers PHP objects and reusable relationships. Compared with a dedicated JSON serialization library, it supplies Schema.org-specific methods and generated type classes. The package is less general than a serializer because its main purpose is vocabulary-aware entity construction.

Limitations, Licensing, and Upgrade Cost

The first limitation is that generation does not guarantee correctness for a particular page. A LocalBusiness object can contain an email or an Organization object, but the package does not establish that the data is truthful, complete, visible on the page, or accepted by a search engine. The README explicitly recommends checking structured data with Google's structured data testing tool. That recommendation identifies the boundary: serialization is local, while validation is external.

The second limitation is the possible gap between generated methods and newer Schema.org terms. The README names one standards file, so applications that depend on recently added vocabulary should inspect src and the package version before coding against a property. setProperty can bypass the missing method, but that method does not add type safety or documentation for the custom key.

The package is also not the right tool when an application only needs one static JSON-LD block. For a fixed script with no PHP entity model, manual JSON or a general-purpose serializer may be simpler. It is better suited when several PHP code paths build related Schema.org objects or when typed property names reduce repeated string keys. It is not a full SEO platform, a crawler, or a policy engine.

Maintenance information is comparatively current for this repository: it is not archived, the last push was on 2026-09-30, and the latest listed release is 5.0.2. The MIT license permits use and modification under its terms, but applications should review the license file and dependency metadata themselves. Upgrade cost is primarily code review around generated type changes, custom properties, and serialization expectations.

Editorial conclusion

Adopt spatie/schema-org when a PHP application needs to create Schema.org JSON-LD through typed objects and fluent calls, especially when nested entities or multiple graph items are involved. Do not treat it as a validator or a replacement for checking search-engine requirements. Verify the generated script, Schema.org vocabulary version, and page-specific structured-data requirements before publishing.

Frequently asked questions

How do I install spatie/schema-org in PHP?

Install it with Composer using `composer require spatie/schema-org`. The README does not document a separate configuration or initialization step.

How does spatie/schema-org generate JSON-LD?

It builds Schema.org objects through a fluent API and can render them with `toScript()`, `toArray()`, or `json_encode()`. Nested schema objects are included in the resulting structure, as shown by the LocalBusiness and ContactPoint example.

Can spatie/schema-org represent multiple related Schema.org entities?

Yes. The README documents a `Graph` class for multiple items and gives an example linking a Product to an Organization, including the ability to hide a selected class from the generated script. The graph example is truncated, so it does not show the complete output or every graph option.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. spatie/schema-org on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/spatie-schema-org.svg)](https://hysenlabs.com/projects/spatie-schema-org)

Was this useful?