jreviews:listing:structured_data
Allows filtering the Schema.org structured-data array before JSON-LD conversion. The array represents the complete assembled output for the listing's primary schema type plus admin-configured enrichments; modify or remove entries to control what's emitted.
You need to have a working knowledge of Hooks before you get started.
Fires when adding Schema.org structured data to listing detail pages, after data is generated but before JSON-LD conversion
Parameters
| Name | Type | Description |
|---|---|---|
$schemaArray |
array |
The assembled structured data array, before JSON-LD conversion |
$listing |
\JReviews\App\Models\Listing |
The listing model being displayed |
Boilerplate Code
Use the boilerplate code to start using the filter, and add your own logic to modify the first argument and return it.
fwd_add_filter('jreviews:listing:structured_data', function($schemaArray, $listing)
{
// Your code here
return $schemaArray;
}, 20, 2);
The , 20, N after your callback are the hook priority and the number of arguments your callback accepts. By default, a hook passes your callback only its first argument; for a filter, that is the value being filtered, so a simple function($value) { ... } needs nothing extra. If your callback declares more parameters, such as function($value, $listing) { ... }, you must add N (the parameter count, 2 here). Because N is the fourth argument to fwd_add_filter() or fwd_add_action(), you must also pass the priority (20 is the default). Leaving these off when your callback expects extra parameters causes a Too few arguments to function ... fatal error.
Examples
- Add amenity features from a checkbox field
- Append sameAs profile links
- Add a measured additional property
Add amenity features from a checkbox field
Convert selected checkbox option labels into Schema.org LocationFeatureSpecification entries under amenityFeature.
fwd_add_filter('jreviews:listing:structured_data', function (array $schemaArray, $listing): array {
// Replace 6 with the listing type ID that owns your amenities field.
// This guard prevents the customization from changing every listing type.
$targetListingTypeId = 6;
if ((int) ($listing->listing_type_id ?? 0) !== $targetListingTypeId) {
return $schemaArray;
}
// Replace jr_amenities with your checkbox or multi-select custom field name.
// getFieldText returns the selected option labels, not the stored option values.
$amenityLabels = (array) $listing->getFieldText('jr_amenities', []);
$features = [];
foreach ($amenityLabels as $label) {
$label = trim(strip_tags((string) $label));
if ($label === '') {
continue;
}
$features[] = [
'@type' => 'LocationFeatureSpecification',
'name' => $label,
'value' => true,
];
}
if ($features === []) {
return $schemaArray;
}
$existing = $schemaArray['amenityFeature'] ?? [];
if ($existing && isset($existing['@type'])) {
$existing = [$existing];
}
$schemaArray['amenityFeature'] = array_values(array_merge(
(array) $existing,
$features
));
return $schemaArray;
}, 20, 2);
Append sameAs profile links
Merge official profile URLs into sameAs without replacing values already generated by JReviews or another customization.
fwd_add_filter('jreviews:listing:structured_data', function (array $schemaArray, $listing): array {
// Replace 6 with the listing type ID that has these profile fields.
$targetListingTypeId = 6;
// Only listings from that type should receive these profile links.
if ((int) ($listing->listing_type_id ?? 0) !== $targetListingTypeId) {
return $schemaArray;
}
// Use fields that store official profile or same-entity URLs.
$profileFields = ['jr_facebook', 'jr_instagram', 'jr_youtube'];
$sameAs = (array) ($schemaArray['sameAs'] ?? []);
foreach ($profileFields as $fieldName) {
$url = trim((string) $listing->getFieldValue($fieldName, ''));
if ($url !== '') {
$sameAs[] = $url;
}
}
if ($sameAs !== []) {
$schemaArray['sameAs'] = array_values(array_unique($sameAs));
}
return $schemaArray;
}, 20, 2);
Add a measured additional property
Create one PropertyValue for a numeric custom field when the value needs to be calculated or controlled in code.
fwd_add_filter('jreviews:listing:structured_data', function (array $schemaArray, $listing): array {
// Replace 6 with the listing type ID that has the measurement field.
$targetListingTypeId = 6;
// Only listings from that type should receive this measured property.
if ((int) ($listing->listing_type_id ?? 0) !== $targetListingTypeId) {
return $schemaArray;
}
// Replace jr_wall_height with your numeric custom field name.
$height = $listing->getFieldValue('jr_wall_height');
if (! is_numeric($height)) {
return $schemaArray;
}
$properties = $schemaArray['additionalProperty'] ?? [];
if ($properties && isset($properties['@type'])) {
$properties = [$properties];
}
$properties[] = [
'@type' => 'PropertyValue',
'name' => 'Max. wall height',
'value' => (float) $height,
// MTR is the UN/CEFACT unit code for meters.
'unitCode' => 'MTR',
'unitText' => 'm',
];
$schemaArray['additionalProperty'] = array_values((array) $properties);
return $schemaArray;
}, 20, 2);
Source Files
app/Actions/AddListingDetailStructuredDataAction.php