From 44d9daf3bc7edc3ed344c5178c3c43a7ad8ed553 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 23 Jun 2026 11:27:59 -0500 Subject: [PATCH] feat: add LocalBusiness JSON-LD schema type Adds configurable LocalBusiness structured data with address, contact, geo coordinates, and opening hours. Enabled via plugin parameters. Closes #65 --- .../language/en-GB/plg_system_mokoog.ini | 32 +++++ .../language/en-US/plg_system_mokoog.ini | 32 +++++ source/packages/plg_system_mokoog/mokoog.xml | 129 ++++++++++++++++++ .../src/Extension/MokoOG.php | 9 ++ .../src/Helper/JsonLdBuilder.php | 100 ++++++++++++++ 5 files changed, 302 insertions(+) diff --git a/source/packages/plg_system_mokoog/language/en-GB/plg_system_mokoog.ini b/source/packages/plg_system_mokoog/language/en-GB/plg_system_mokoog.ini index e6fdb6b..2c8029d 100644 --- a/source/packages/plg_system_mokoog/language/en-GB/plg_system_mokoog.ini +++ b/source/packages/plg_system_mokoog/language/en-GB/plg_system_mokoog.ini @@ -39,3 +39,35 @@ PLG_SYSTEM_MOKOOG_FIELD_JSONLD_ENABLED="Enable JSON-LD" PLG_SYSTEM_MOKOOG_FIELD_JSONLD_ENABLED_DESC="Output JSON-LD structured data (Article, WebPage) for Google rich results." PLG_SYSTEM_MOKOOG_FIELD_JSONLD_BREADCRUMBS="JSON-LD Breadcrumbs" PLG_SYSTEM_MOKOOG_FIELD_JSONLD_BREADCRUMBS_DESC="Output BreadcrumbList JSON-LD schema from Joomla's pathway." + +PLG_SYSTEM_MOKOOG_FIELDSET_LOCALBUSINESS="Local Business" +PLG_SYSTEM_MOKOOG_FIELD_LB_ENABLED="Enable LocalBusiness Schema" +PLG_SYSTEM_MOKOOG_FIELD_LB_ENABLED_DESC="Output LocalBusiness JSON-LD structured data on all pages." +PLG_SYSTEM_MOKOOG_FIELD_LB_NAME="Business Name" +PLG_SYSTEM_MOKOOG_FIELD_LB_NAME_DESC="Your business name for structured data." +PLG_SYSTEM_MOKOOG_FIELD_LB_TYPE="Business Type" +PLG_SYSTEM_MOKOOG_FIELD_LB_TYPE_DESC="Schema.org business type." +PLG_SYSTEM_MOKOOG_FIELD_LB_STREET="Street Address" +PLG_SYSTEM_MOKOOG_FIELD_LB_STREET_DESC="Street address of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_CITY="City" +PLG_SYSTEM_MOKOOG_FIELD_LB_CITY_DESC="City of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_REGION="State/Region" +PLG_SYSTEM_MOKOOG_FIELD_LB_REGION_DESC="State or region of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_POSTAL="Postal Code" +PLG_SYSTEM_MOKOOG_FIELD_LB_POSTAL_DESC="Postal/ZIP code of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_COUNTRY="Country" +PLG_SYSTEM_MOKOOG_FIELD_LB_COUNTRY_DESC="Country code (e.g. US, GB, DE)." +PLG_SYSTEM_MOKOOG_FIELD_LB_PHONE="Phone" +PLG_SYSTEM_MOKOOG_FIELD_LB_PHONE_DESC="Business phone number." +PLG_SYSTEM_MOKOOG_FIELD_LB_EMAIL="Email" +PLG_SYSTEM_MOKOOG_FIELD_LB_EMAIL_DESC="Business email address." +PLG_SYSTEM_MOKOOG_FIELD_LB_URL="Website URL" +PLG_SYSTEM_MOKOOG_FIELD_LB_URL_DESC="Business website URL." +PLG_SYSTEM_MOKOOG_FIELD_LB_OPENING_HOURS="Opening Hours" +PLG_SYSTEM_MOKOOG_FIELD_LB_OPENING_HOURS_DESC="Opening hours in schema.org format (e.g. Mo-Fr 09:00-17:00)." +PLG_SYSTEM_MOKOOG_FIELD_LB_LATITUDE="Latitude" +PLG_SYSTEM_MOKOOG_FIELD_LB_LATITUDE_DESC="Geographic latitude of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_LONGITUDE="Longitude" +PLG_SYSTEM_MOKOOG_FIELD_LB_LONGITUDE_DESC="Geographic longitude of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_PRICE_RANGE="Price Range" +PLG_SYSTEM_MOKOOG_FIELD_LB_PRICE_RANGE_DESC="Price range indicator (e.g. $, $$, $$$)." diff --git a/source/packages/plg_system_mokoog/language/en-US/plg_system_mokoog.ini b/source/packages/plg_system_mokoog/language/en-US/plg_system_mokoog.ini index e6fdb6b..2c8029d 100644 --- a/source/packages/plg_system_mokoog/language/en-US/plg_system_mokoog.ini +++ b/source/packages/plg_system_mokoog/language/en-US/plg_system_mokoog.ini @@ -39,3 +39,35 @@ PLG_SYSTEM_MOKOOG_FIELD_JSONLD_ENABLED="Enable JSON-LD" PLG_SYSTEM_MOKOOG_FIELD_JSONLD_ENABLED_DESC="Output JSON-LD structured data (Article, WebPage) for Google rich results." PLG_SYSTEM_MOKOOG_FIELD_JSONLD_BREADCRUMBS="JSON-LD Breadcrumbs" PLG_SYSTEM_MOKOOG_FIELD_JSONLD_BREADCRUMBS_DESC="Output BreadcrumbList JSON-LD schema from Joomla's pathway." + +PLG_SYSTEM_MOKOOG_FIELDSET_LOCALBUSINESS="Local Business" +PLG_SYSTEM_MOKOOG_FIELD_LB_ENABLED="Enable LocalBusiness Schema" +PLG_SYSTEM_MOKOOG_FIELD_LB_ENABLED_DESC="Output LocalBusiness JSON-LD structured data on all pages." +PLG_SYSTEM_MOKOOG_FIELD_LB_NAME="Business Name" +PLG_SYSTEM_MOKOOG_FIELD_LB_NAME_DESC="Your business name for structured data." +PLG_SYSTEM_MOKOOG_FIELD_LB_TYPE="Business Type" +PLG_SYSTEM_MOKOOG_FIELD_LB_TYPE_DESC="Schema.org business type." +PLG_SYSTEM_MOKOOG_FIELD_LB_STREET="Street Address" +PLG_SYSTEM_MOKOOG_FIELD_LB_STREET_DESC="Street address of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_CITY="City" +PLG_SYSTEM_MOKOOG_FIELD_LB_CITY_DESC="City of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_REGION="State/Region" +PLG_SYSTEM_MOKOOG_FIELD_LB_REGION_DESC="State or region of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_POSTAL="Postal Code" +PLG_SYSTEM_MOKOOG_FIELD_LB_POSTAL_DESC="Postal/ZIP code of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_COUNTRY="Country" +PLG_SYSTEM_MOKOOG_FIELD_LB_COUNTRY_DESC="Country code (e.g. US, GB, DE)." +PLG_SYSTEM_MOKOOG_FIELD_LB_PHONE="Phone" +PLG_SYSTEM_MOKOOG_FIELD_LB_PHONE_DESC="Business phone number." +PLG_SYSTEM_MOKOOG_FIELD_LB_EMAIL="Email" +PLG_SYSTEM_MOKOOG_FIELD_LB_EMAIL_DESC="Business email address." +PLG_SYSTEM_MOKOOG_FIELD_LB_URL="Website URL" +PLG_SYSTEM_MOKOOG_FIELD_LB_URL_DESC="Business website URL." +PLG_SYSTEM_MOKOOG_FIELD_LB_OPENING_HOURS="Opening Hours" +PLG_SYSTEM_MOKOOG_FIELD_LB_OPENING_HOURS_DESC="Opening hours in schema.org format (e.g. Mo-Fr 09:00-17:00)." +PLG_SYSTEM_MOKOOG_FIELD_LB_LATITUDE="Latitude" +PLG_SYSTEM_MOKOOG_FIELD_LB_LATITUDE_DESC="Geographic latitude of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_LONGITUDE="Longitude" +PLG_SYSTEM_MOKOOG_FIELD_LB_LONGITUDE_DESC="Geographic longitude of your business." +PLG_SYSTEM_MOKOOG_FIELD_LB_PRICE_RANGE="Price Range" +PLG_SYSTEM_MOKOOG_FIELD_LB_PRICE_RANGE_DESC="Price range indicator (e.g. $, $$, $$$)." diff --git a/source/packages/plg_system_mokoog/mokoog.xml b/source/packages/plg_system_mokoog/mokoog.xml index 4bae4a6..d87c2a5 100644 --- a/source/packages/plg_system_mokoog/mokoog.xml +++ b/source/packages/plg_system_mokoog/mokoog.xml @@ -181,6 +181,135 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/source/packages/plg_system_mokoog/src/Extension/MokoOG.php b/source/packages/plg_system_mokoog/src/Extension/MokoOG.php index e3fbb0e..05d0bd3 100644 --- a/source/packages/plg_system_mokoog/src/Extension/MokoOG.php +++ b/source/packages/plg_system_mokoog/src/Extension/MokoOG.php @@ -298,6 +298,15 @@ final class MokoOG extends CMSPlugin implements SubscriberInterface } } } + + // LocalBusiness JSON-LD + if ($this->params->get('lb_enabled', 0)) { + $lbSchema = JsonLdBuilder::buildLocalBusiness($this->params); + + if ($lbSchema) { + $doc->addCustomTag(JsonLdBuilder::toScriptTag($lbSchema)); + } + } } /** diff --git a/source/packages/plg_system_mokoog/src/Helper/JsonLdBuilder.php b/source/packages/plg_system_mokoog/src/Helper/JsonLdBuilder.php index 1f304af..649bf07 100644 --- a/source/packages/plg_system_mokoog/src/Helper/JsonLdBuilder.php +++ b/source/packages/plg_system_mokoog/src/Helper/JsonLdBuilder.php @@ -282,6 +282,106 @@ class JsonLdBuilder return $schema; } + /** + * Build LocalBusiness schema from plugin parameters. + * + * @param object $params Plugin parameters object + * + * @return array|null + */ + public static function buildLocalBusiness(object $params): ?array + { + $name = trim((string) $params->get('lb_name', '')); + + if ($name === '') { + return null; + } + + $schema = [ + '@context' => 'https://schema.org', + '@type' => $params->get('lb_type', 'LocalBusiness'), + 'name' => $name, + ]; + + // Build PostalAddress + $address = []; + $street = trim((string) $params->get('lb_street', '')); + $city = trim((string) $params->get('lb_city', '')); + $region = trim((string) $params->get('lb_region', '')); + $postal = trim((string) $params->get('lb_postal', '')); + $country = trim((string) $params->get('lb_country', '')); + + if ($street !== '') { + $address['streetAddress'] = $street; + } + + if ($city !== '') { + $address['addressLocality'] = $city; + } + + if ($region !== '') { + $address['addressRegion'] = $region; + } + + if ($postal !== '') { + $address['postalCode'] = $postal; + } + + if ($country !== '') { + $address['addressCountry'] = $country; + } + + if (!empty($address)) { + $address['@type'] = 'PostalAddress'; + $schema['address'] = $address; + } + + // Contact properties + $phone = trim((string) $params->get('lb_phone', '')); + $email = trim((string) $params->get('lb_email', '')); + $url = trim((string) $params->get('lb_url', '')); + + if ($phone !== '') { + $schema['telephone'] = $phone; + } + + if ($email !== '') { + $schema['email'] = $email; + } + + if ($url !== '') { + $schema['url'] = $url; + } + + // Opening hours + $openingHours = trim((string) $params->get('lb_opening_hours', '')); + + if ($openingHours !== '') { + $schema['openingHours'] = $openingHours; + } + + // GeoCoordinates + $latitude = trim((string) $params->get('lb_latitude', '')); + $longitude = trim((string) $params->get('lb_longitude', '')); + + if ($latitude !== '' && $longitude !== '') { + $schema['geo'] = [ + '@type' => 'GeoCoordinates', + 'latitude' => $latitude, + 'longitude' => $longitude, + ]; + } + + // Price range + $priceRange = trim((string) $params->get('lb_price_range', '')); + + if ($priceRange !== '') { + $schema['priceRange'] = $priceRange; + } + + return $schema; + } + /** * Encode a schema array to a JSON-LD script tag string. *