{"id":13554261,"url":"https://github.com/spatie/schema-org","last_synced_at":"2026-10-19T12:42:39.807Z","repository":{"id":38553645,"uuid":"74684096","full_name":"spatie/schema-org","owner":"spatie","description":"A fluent builder Schema.org types and ld+json generator","archived":false,"fork":false,"pushed_at":"2026-09-30T06:10:17.000Z","size":9488,"stargazers_count":1510,"open_issues_count":0,"forks_count":146,"subscribers_count":37,"default_branch":"main","last_synced_at":"2026-10-14T09:41:43.954Z","etag":null,"topics":["google","php","schedule","schema","seo"],"latest_commit_sha":null,"homepage":"https://freek.dev/2016/12/package-fluently-generate-schema-org-markup/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spatie.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"spatie","custom":"https://spatie.be/open-source/support-us"}},"created_at":"2016-11-24T15:15:37.000Z","updated_at":"2026-10-12T12:14:00.000Z","dependencies_parsed_at":"2025-02-06T05:01:30.817Z","dependency_job_id":"dbeab1e4-20a6-46db-8a17-a8e0af7da383","html_url":"https://github.com/spatie/schema-org","commit_stats":{"total_commits":369,"total_committers":37,"mean_commits":9.972972972972974,"dds":0.5962059620596206,"last_synced_commit":"111488e5110da30cc96b775b480bc29b28164883"},"previous_names":[],"tags_count":65,"template":false,"template_full_name":null,"purl":"pkg:github/spatie/schema-org","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Fschema-org","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Fschema-org/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Fschema-org/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Fschema-org/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spatie","download_url":"https://codeload.github.com/spatie/schema-org/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spatie%2Fschema-org/sbom","scorecard":{"id":840651,"data":{"date":"2025-08-11","repo":{"name":"github.com/spatie/schema-org","commit":"f0abf07f998fc412acfa694f04f7dbc1bff079cb"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":1,"reason":"1 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":1,"reason":"Found 3/19 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 19 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-23T20:24:17.266Z","repository_id":38553645,"created_at":"2025-08-23T20:24:17.266Z","updated_at":"2025-08-23T20:24:17.266Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":344794859,"owners_count":38311489,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-10-03T21:59:58.778Z","status":"online","status_checked_at":"2026-10-14T02:00:06.392Z","response_time":82,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google","php","schedule","schema","seo"],"created_at":"2024-08-01T12:02:43.511Z","updated_at":"2026-10-19T12:42:39.800Z","avatar_url":"https://github.com/spatie.png","language":"PHP","funding_links":["https://github.com/sponsors/spatie","https://spatie.be/open-source/support-us"],"categories":["PHP","Open-Source Repos \u0026 Tools","Data and Storage","seo"],"sub_categories":["Structured Data \u0026 Schema","Serialization and Formats"],"readme":"\u003cdiv align=\"left\"\u003e\n    \u003ca href=\"https://spatie.be/open-source?utm_source=github\u0026utm_medium=banner\u0026utm_campaign=schema-org\"\u003e\n      \u003cpicture\u003e\n        \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://spatie.be/packages/header/schema-org/html/dark.webp\"\u003e\n        \u003cimg alt=\"Logo for schema-org\" src=\"https://spatie.be/packages/header/schema-org/html/light.webp\"\u003e\n      \u003c/picture\u003e\n    \u003c/a\u003e\n\n\u003ch1\u003eA Fluent Builder For Schema.org Types And ld+json Generator\u003c/h1\u003e\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/spatie/schema-org.svg?style=flat-square)](https://packagist.org/packages/spatie/schema-org)\n[![MIT License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)\n[![Total Downloads](https://img.shields.io/packagist/dt/spatie/schema-org.svg?style=flat-square)](https://packagist.org/packages/spatie/schema-org)\n  \n\u003c/div\u003e\n\n`spatie/schema-org` provides a fluent builder for **all** Schema.org types and their properties. The code in `src` is generated from Schema.org's [JSON-LD standards file](https://raw.githubusercontent.com/schemaorg/schemaorg/main/data/releases/13.0/schemaorg-all-https.jsonld), so it provides objects and methods for the entire core vocabulary. The classes and methods are also fully documented as a quick reference.\n\n```php\nuse Spatie\\SchemaOrg\\Schema;\n\n$localBusiness = Schema::localBusiness()\n    -\u003ename('Spatie')\n    -\u003eemail('info@spatie.be')\n    -\u003econtactPoint(Schema::contactPoint()-\u003eareaServed('Worldwide'));\n\necho $localBusiness-\u003etoScript();\n```\n\n```html\n\u003cscript type=\"application/ld+json\"\u003e\n{\n    \"@context\": \"https:\\/\\/schema.org\",\n    \"@type\": \"LocalBusiness\",\n    \"name\": \"Spatie\",\n    \"email\": \"info@spatie.be\",\n    \"contactPoint\": {\n        \"@type\": \"ContactPoint\",\n        \"areaServed\": \"Worldwide\"\n    }\n}\n\u003c/script\u003e\n```\n\n## Support us\n\n[\u003cimg src=\"https://github-ads.s3.eu-central-1.amazonaws.com/schema-org.jpg?t=1\" width=\"419px\" /\u003e](https://spatie.be/github-ad-click/schema-org)\n\nWe invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).\n\nWe highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).\n\n## Installation\n\nYou can install the package via composer:\n\n``` bash\ncomposer require spatie/schema-org\n```\n\n## Usage\n\nAll types can be instantiated through the `Spatie\\SchemaOrg\\Schema` factory class, or with the `new` keyword.\n\n``` php\n$localBusiness = Schema::localBusiness()-\u003ename('Spatie');\n\n// Is equivalent to:\n\n$localBusiness = new LocalBusiness();\n$localBusiness-\u003ename('Spatie');\n```\n\n\u003e *All types also accept arrays of the expected data type, for example `sameAs` accepts a string or an array of strings.*\n\nAll types also implement the SPL's `ArrayAccess` for accessing the properties via array notation:\n\n```php\n$anotherLocalBusiness = new LocalBusiness();\nvar_dump(isset($anotherLocalBusiness['name'])); // =\u003e false\n$anotherLocalBusiness['name'] = 'Spatie';\nvar_dump(isset($anotherLocalBusiness['name'])); // =\u003e true\nvar_dump($anotherLocalBusiness['name']); // =\u003e 'Spatie'\nunset($anotherLocalBusiness['name']);\nvar_dump(isset($anotherLocalBusiness['name'])); // =\u003e false\n```\n\nTypes can be converted to an array or rendered to a script.\n\n```php\n$localBusiness-\u003etoArray();\n\necho $localBusiness-\u003etoScript();\n\necho $localBusiness; // Same output as `toScript()`\n```\n\nAdditionally, all types can be converted to a plain JSON string by just calling `json_encode()` with your object:\n\n```php\necho json_encode($localBusiness);\n```\n\nI recommend double checking your structured data with [Google's structured data testing tool](https://search.google.com/structured-data/testing-tool).\n\n### Enumerations\n\nAs of v1.6.0, all [Enumeration](https://schema.org/Enumeration) child types are available as classes with constants.\n\n```php\nSchema::book()-\u003ebookFormat(Spatie\\SchemaOrg\\BookFormatType::Hardcover);\n```\n\nThere's no full API documentation for types and properties. You can refer to [the source](https://github.com/spatie/schema-org/tree/master/src) or to [the schema.org website](https://schema.org).\n\nIf you don't want to break the chain of a large schema object, you can use the `if` method to conditionally modify the schema.\n\n```php\nuse Spatie\\SchemaOrg\\LocalBusiness;\nuse Spatie\\SchemaOrg\\Schema;\n\n$business = ['name' =\u003e 'Spatie'];\n\n$localBusiness = Schema::localBusiness()\n    -\u003ename($business['name'])\n    -\u003eif(isset($business['email']), function (LocalBusiness $schema) use ($business) {\n        $schema-\u003eemail($business['email']);\n    });\n```\n\n### Identifier\n\nAs of v2.6.0 the `identifier` key is replaced by `@id` for simple string identifiers. This is due to the definition for the `ld+json` syntax.\n\n\u003e All schema.org syntaxes already have built-in representation for URIs and URLs, e.g. in Microdata 'itemid', in RDFa 1.1, 'resource', **in JSON-LD, '@id'.**\n\u003e \n\u003e \u0026mdash; [schema.org/docs](https://schema.org/docs/datamodel.html#identifierBg) // [PR#102](https://github.com/spatie/schema-org/pull/102)  // [PR#157](https://github.com/spatie/schema-org/pull/157) \n\n### Advanced Usage\n\nIf you'd need to set a custom property, you can use the `setProperty` method.\n\n```php\n$localBusiness-\u003esetProperty('foo', 'bar');\n```\n\nIf you'd need to retrieve a property, you can use the `getProperty` method. You can optionally pass in a second parameter to provide a default value.\n\n```php\n$localBusiness-\u003egetProperty('name'); // 'Spatie'\n$localBusiness-\u003egetProperty('bar'); // null\n$localBusiness-\u003egetProperty('bar', 'baz'); // 'baz'\n```\n\nAll properties can be retrieved as an array with the `getProperties` method.\n\n```php\n$localBusiness-\u003egetProperties(); // ['name' =\u003e 'Spatie', ...]\n```\n\nMultiple properties can be set at once using the `addProperties` method.\n\n```php\n$localBusiness-\u003eaddProperties(['name' =\u003e 'value', 'foo' =\u003e 'bar']);\n```\n\nContext and type can be retrieved with the `getContext` and `getType` methods.\n\n```php\n$localBusiness-\u003egetContext(); // 'https://schema.org'\n$localBusiness-\u003egetType(); // 'LocalBusiness'\n```\n\n### Graph - multiple items\n\nThe Graph has a lot of methods and utilities - the type-safe and simplest way is to use the overloaded methods of the `Spatie\\SchemaOrg\\Schema` class itself. These methods will get an already created or new instance of the requested schema.\n\n```php\n$graph = new Graph();\n\n// Create a product and prelink organization\n$graph\n    -\u003eproduct()\n    -\u003ename('My cool Product')\n    -\u003ebrand($graph-\u003eorganization());\n\n// Hide the organization from the created script tag\n$graph-\u003ehide(\\Spatie\\SchemaOrg\\Organization::class);\n\n// Somewhere else fill out the organization\n$graph\n    -\u003eorganization()\n    -\u003ename('My awesome Company');\n\n// Render graph to script tag\necho $graph;\n```\n\nWith these tools the graph is a collection of all available schemas, can link these schemas with each other and prevent helper schemas from being rendered in the script-tag.\n\n### Graph Node identifiers\n\nSometimes you have to keep track of multiple Graph nodes of the same type - for example multiple `Person` nodes for different people in your Organization.\nTo do so you are able to use node identifiers on your graph instance.\nIf you don't provide an identifier a reserved keyword `default` identifier will be used.\n\n```php\nuse Spatie\\SchemaOrg\\Graph;\nuse Spatie\\SchemaOrg\\Person;\n\n$graph = new Graph();\n\n// add a Person using chaining\n$graph-\u003eperson('freekmurze')\n    -\u003egivenName('Freek')\n    -\u003efamilyName('Van der Herten')\n    -\u003ealternateName('freekmurze');\n\n// add a Person using closure\n$graph-\u003eperson('sebastiandedeyne', function(Person $sebastian, Graph $graph): void {\n    $sebastian\n        -\u003egivenName('Sebastian')\n        -\u003efamilyName('De Deyne')\n        -\u003ealternateName('sebastiandedeyne');\n}); \n\n// add a person using closure and second call with same identifier\n$graph-\u003eperson(\n    'gummibeer', \n    fn(Person $gummibeer) =\u003e $gummibeer-\u003ealternateName('gummibeer')\n);\n$graph-\u003eperson('gummibeer')\n    -\u003egivenName('Tom')\n    -\u003efamilyName('Witkowski');\n\n$graph-\u003eperson('random')-\u003ename('Random Person');\n\n// hide the random person from Graph\n$graph-\u003ehide(Person::class, 'random');\n\necho json_encode($graph);\n```\n\n```json\n{\n    \"@context\":\"https:\\/\\/schema.org\",\n    \"@graph\":[\n        {\n            \"@type\":\"Person\",\n            \"givenName\":\"Freek\",\n            \"familyName\":\"Van der Herten\",\n            \"alternateName\":\"freekmurze\"\n        },\n        {\n            \"@type\":\"Person\",\n            \"givenName\":\"Sebastian\",\n            \"familyName\":\"De Deyne\",\n            \"alternateName\":\"sebastiandedeyne\"\n        },\n        {\n            \"@type\":\"Person\",\n            \"alternateName\":\"gummibeer\",\n            \"givenName\":\"Tom\",\n            \"familyName\":\"Witkowski\"\n        }\n    ]\n}\n```\n\n### Multi Typed Entities\n\nSchema.org allows [multi typed entities](https://github.com/schemaorg/schemaorg/wiki/How-to-use-Multi-Typed-Entities-or-MTEs) - to use them with this package you can use the `MultiTypedEntity` class - which works similar to the graph.\n\n```php\n$mte = new MultiTypedEntity();\n$mte-\u003ehotelRoom()-\u003ename('The Presidential Suite');\n$mte-\u003eproduct()-\u003eoffers(\n    Schema::offer()\n        -\u003ename('One Night')\n        -\u003eprice(100000.00)\n        -\u003epriceCurrency('USD')\n);\n$mte-\u003eproduct(function (Product $product) {\n    $product-\u003eaggregateRating(\n        Schema::aggregateRating()\n            -\u003ebestRating(5)\n            -\u003eworstRating(4)\n    );\n});\n\necho json_encode($mte);\n```\n\n```json\n{\n   \"@context\":\"https:\\/\\/schema.org\",\n   \"@type\":[\n      \"HotelRoom\",\n      \"Product\"\n   ],\n   \"name\":\"The Presidential Suite\",\n   \"offers\":{\n      \"@type\":\"Offer\",\n      \"name\":\"One Night\",\n      \"price\":100000,\n      \"priceCurrency\":\"USD\"\n   },\n   \"aggregateRating\":{\n      \"@type\":\"AggregateRating\",\n      \"bestRating\":5,\n      \"worstRating\":4\n   }\n}\n```\n\nThere isn't a real rule in place how the properties are merged. It only uses `array_merge()` behind the scenes. So you should avoid defining the same property on different types in the MTE or be sure that all properties hold the same value that it's not important which property is used at the end.\n\n## Known Issues\n\n- The `Float` type isn't available since it's a reserved keyword in PHP\n\n## Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.\n\n## Testing\n\n``` bash\n$ composer test\n```\n\n## Contributing\n\nPlease see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.\n\n## Security\n\nIf you've found a bug regarding security please mail [security@spatie.be](mailto:security@spatie.be) instead of using the issue tracker.\n\n## Postcardware\n\nYou're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.\n\nOur address is: Spatie, Kruikstraat 22, 2018 Antwerp, Belgium.\n\nWe publish all received postcards [on our company website](https://spatie.be/en/opensource/postcards).\n\n## Credits\n\n- [Sebastian De Deyne](https://github.com/sebastiandedeyne)\n- [Tom Witkowski](https://github.com/Gummibeer)\n- [All Contributors](../../contributors)\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspatie%2Fschema-org","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspatie%2Fschema-org","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspatie%2Fschema-org/lists"}