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.
Start here
Copy the boilerplate below, then add the logic you need. Return the modified first argument. New to hooks? Read the hooks primer first.
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
Paste this into your hook file, then add your logic and return the modified first argument.
fwd_add_filter('jreviews:listing:structured_data', function($schemaArray, $listing)
{
// Your code here
return $schemaArray;
}, 20, 2);
, 20, N sets the priority and how many arguments your callback accepts. If you use both $filterResult and $listing, keep , 20, 2 so both are passed to your callback.
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