Structured Data Markup Rendering for TYPO3 with JSON-LD
PxSemantic provides an extrem dynamic and highly customizable solution to embed structured data on your website and enrich them with information about your website. The currently supported classes are a subset of the vocabulary defined on https://schema.org/ and were generated with the schema generator from https://api-platform.com/. At the moment we only support json-ld format to encode LinkedData.
Before you start:
For example you want to markup your official website with information about your corporate contacts (https://developers.google.com/structured-data/customize/contact-points) you can do it this way:
Declare your organization information and corporate contact via TypoScript.
lib.structuredDataMarkupOrganization < lib.structuredDataMarkup
lib.structuredDataMarkupOrganization {
settings {
entity = Portrino\PxSemantic\SchemaOrg\Organization
processors {
# processor to set properties of an entity via TypoScript
0 {
className = Portrino\PxSemantic\Processor\TypoScriptProcessor
settings {
# for string values you do not have to use TEXT datatype, you can just write "key = value"
# US, GB, DE
areaServed = DE
contactPoint {
# "customer support", "technical support", "billing support", ...
contactType = customer support
telephone = +49-123-456-78
}
logo {
# get the logo image uri via TS and prepend the baseUrl to get the absolute path
url = IMG_RESOURCE
url {
file = fileadmin/company_logo.png
stdWrap.wrap = {TSFE:baseUrl}|
stdWrap.insertData = 1
}
}
# special datatype from px_semantic EXT to define arrays
sameAs = Portrino\PxSemantic\Converter\ArrayConverter
sameAs {
0 = http://www.facebook.com/yourSite/
1 = http://www.youtube.com/user/yourSite/
2 = http://www.pinterest.com/yourSite/
}
# use typolink to generate link to the root page
url = TEXT
url.typolink {
parameter = 1
returnLast = url
}
}
}
}
}
}
Use the TS to render the resulting JSON-LD code somewhere on your website. We put it into the <HEAD>
because other
meta information are also located within the <HEAD>
tag. But it doesn`t matter.
Google says:
You can embed data in a web page using schema.org field names and the new JSON-LD data format. JSON-LD is easy to produce with many widely available JSON encoders. The data, enclosed within the
or region of the page that displays that event. Either way, it won't affect how your document appears in users' web browsers. -- [Google Documentation][1]<script type="application/ld+json"> ... </script>
tags as shown in the examples below, may be placed in either the
page.headerData.1453734422 < lib.structuredDataMarkupOrganization
If you want to put it in your template you could make use fluids cObject
-ViewHelper:
<f:cObject typoscriptObjectPath="lib.structuredDataMarkupOrganization"></f:cObject>
This will result in the following JSON-LD Markup on your page
<script type="application/ld+json">
{
"@context" : "http://schema.org",
"@type" : "Organization",
"areaServed":"DE"
"url" : "http://www.your-company-site.com",
"contactPoint" : {
"@type" : "ContactPoint",
"areaServed":"DE",
"telephone" : "+49-123-456-78",
"contactType" : "customer support"
},
"logo": {
"@type":"ImageObject",
"url":"http://www.your-company-site.com/fileadmin/company_logo.png"
},
"sameAs":[
"http:\\www.facebook.com\yourSite",
"http:\\www.youtube.com\user\yourSite",
"http:\\www.pinterest.com\yourSite\"
]
}
</script>
TypoScript:
lib.structuredDataMarkupExample < lib.structuredDataMarkup
lib.structuredDataMarkupExample {
settings {
entity {
className = Portrino\PxSemantic\SchemaOrg\Question
id = TEXT
id.data = field:uid
}
processors {
0 {
className = Portrino\PxSemantic\Processor\ExampleProcessor
}
}
}
}
Fluid:
<f:for each="{entities}" as="entity">
{entity -> f:cObject(typoscriptObjectPath: 'lib.structuredDataMarkupExample')}
</f:for>
Since version 2.0.0 it is possible to configure an LinkedData REST API which is based on Hydra Core Vocabulary (http://www.hydra-cg.com/spec/latest/core/)
TypoScript:
- create a page e.g. called "api (123)" within your page tree for better realurl configuration
constants.txt
plugin.tx_pxsemantic {
settings {
rest {
pid = 123
}
}
}
}
- now configure for each endpoint of your rest api the resource to entity mapping like in the easy example below
- as for strcutured data markup in exampe 1 and example 2 you could (re)use
processors
to transform your resource (aka domain model) into an http://schema.org/ entity
setup.txt
plugin.tx_pxsemantic {
settings {
rest {
endpoints {
pages {
entity = Portrino\PxSemantic\SchemaOrg\CreativeWork
resource = Portrino\PxSemantic\Domain\Model\Page
processors {
0 {
className = Portrino\PxSemantic\Processor\PageProcessor
}
}
}
}
}
}
}
}
- add this realurl configuration for nicer uris of your rest API
realurl_conf.php
...
'fixedPostVars' => [
'_DEFAULT' => [],
'api' => [
[
'GETvar' => 'type',
'valueMap' => [
'structured-data' => 1475825939,
'structured-data-contexts' => 1476721757,
'vocab' => 1476770090
]
],
[
'GETvar' => 'tx_pxsemantic_hydraapi[endpoint]',
'valueMap' => [
'recipes' => 'recipes',
'pages' => 'pages'
],
'noMatch' => 'bypass'
],
[
'GETvar' => 'tx_pxsemantic_hydracontext[context]',
'valueMap' => [
'Entrypoint' => 'Entrypoint',
],
'noMatch' => 'bypass'
],
[
'cond' => [
'prevValueInList' => 'pages'
],
'GETvar' => 'tx_pxsemantic_hydraapi[uid]',
'lookUpTable' => [
'table' => 'pages',
'id_field' => 'uid',
'alias_field' => 'uid'
],
'optional' => true
]
],
'123' => 'api'
],
...
-
now you can call your Linked Data REST API via: http://domain.tld/api/structured-data/pages/ which will be presented as PagedCollection (http://www.hydra-cg.com/spec/latest/core/#collections)
-
add this url to hydra console (http://www.markus-lanthaler.com/hydra/console/) will give you a nice hydra documentation
- Could be found under: https://github.com/portrino/px-semantic-demo
- André Wuttig - Initial work, Semantic REST API, Documentation - aWuttig
- Axel Böswetter - some more semantic.org entities - EvilBMP
See also the list of contributors who participated in this project.