diff --git a/lang/en/fieldsets/defaults.php b/lang/en/fieldsets/defaults.php index 45268a64..0f07003d 100644 --- a/lang/en/fieldsets/defaults.php +++ b/lang/en/fieldsets/defaults.php @@ -26,7 +26,7 @@ 'json_ld_section' => 'JSON-LD', 'json_ld_entity_section' => 'Entity Information', - 'json_ld_entity_section_instruct' => 'Basic details about the organization or person this site represents.', + 'json_ld_entity_section_instruct' => 'Basic details about the organization or person this site represents. This schema is only output on the homepage, as [recommended by Google](https://developers.google.com/search/docs/appearance/structured-data/organization).', 'json_ld_entity' => 'Entity', 'json_ld_entity_instruct' => 'This helps search engines understand the structured data on your site and improves the likelihood of it appearing with rich search results.', 'json_ld_organization_name' => 'Organization Name', @@ -37,9 +37,9 @@ 'json_ld_person_name_instruct' => 'The full name of the person this site represents.', 'json_ld_custom_section' => 'Custom Schema', - 'json_ld_custom_section_instruct' => 'Add custom JSON-LD schema that will be included on every page across your site.', + 'json_ld_custom_section_instruct' => 'Add a custom JSON-LD schema that will be output on every page across your site.', 'json_ld_schema' => 'Schema', - 'json_ld_schema_instruct' => 'Paste your custom schema objects here (`LocalBusiness`, `SoftwareApplication`, etc). You can use Antlers to output data from the item. Will be wrapped in the appropriate script tag.', + 'json_ld_schema_instruct' => 'Paste your custom schema objects here (`WebSite`, `SiteNavigationElement`, etc). Will be wrapped in the appropriate script tag.', 'json_ld_breadcrumbs_section' => 'Breadcrumbs', 'json_ld_breadcrumbs' => 'Breadcrumbs', diff --git a/src/Cascade.php b/src/Cascade.php index 0908dba6..f6fcb48b 100644 --- a/src/Cascade.php +++ b/src/Cascade.php @@ -171,6 +171,18 @@ public function homeUrl() return Site::current()?->absoluteUrl() ?? URL::makeAbsolute('/'); } + protected function isHomePage(): bool + { + if (! method_exists($this->model, 'absoluteUrl')) { + return false; + } + + $home = Str::removeRight((string) $this->site()->absoluteUrl(), '/'); + $current = Str::removeRight((string) $this->model->absoluteUrl(), '/'); + + return $current !== '' && $current === $home; + } + public function canonicalUrl() { $url = URL::tidy(Str::trim($this->explicitUrl ?? $this->data->get('canonical_url'))); @@ -619,7 +631,7 @@ protected function jsonLd() $jsonLdOrganizationLogo = $this->data->get('json_ld_organization_logo'); $jsonLdPersonName = (string) $this->data->get('json_ld_person_name'); - if ($jsonLdEntity === 'organization' && $jsonLdOrganizationName) { + if ($this->isHomePage() && $jsonLdEntity === 'organization' && $jsonLdOrganizationName) { if ($jsonLdOrganizationLogo && ! $jsonLdOrganizationLogo instanceof Value) { $jsonLdOrganizationLogo = Asset::find($jsonLdOrganizationLogo); } @@ -634,7 +646,7 @@ protected function jsonLd() ]), JSON_UNESCAPED_SLASHES)); } - if ($jsonLdEntity === 'person' && $jsonLdPersonName) { + if ($this->isHomePage() && $jsonLdEntity === 'person' && $jsonLdPersonName) { $snippets->push(json_encode([ '@context' => 'https://schema.org', '@type' => 'Person', diff --git a/tests/CascadeTest.php b/tests/CascadeTest.php index 979bfe34..f8d499d8 100644 --- a/tests/CascadeTest.php +++ b/tests/CascadeTest.php @@ -442,6 +442,58 @@ public function it_generates_json_ld_data_with_custom_schema_from_site_defaults( ], $data['json_ld']->all()); } + #[Test] + public function it_only_outputs_organization_schema_on_the_homepage() + { + $siteDefaults = SiteDefaults::in('default')->set([ + 'json_ld_entity' => 'organization', + 'json_ld_organization_name' => 'Cool Runnings Ltd', + ]); + + $home = (new Cascade) + ->with($siteDefaults->all()) + ->withCurrent(Entry::findByUri('/')) + ->get(); + + $this->assertContains( + '{"@context":"https://schema.org","@type":"Organization","name":"Cool Runnings Ltd","@id":"http://cool-runnings.com#organization","url":"http://cool-runnings.com"}', + $home['json_ld']->all() + ); + + $about = (new Cascade) + ->with($siteDefaults->all()) + ->withCurrent(Entry::findByUri('/about')) + ->get(); + + $this->assertEmpty($about['json_ld']->all()); + } + + #[Test] + public function it_only_outputs_person_schema_on_the_homepage() + { + $siteDefaults = SiteDefaults::in('default')->set([ + 'json_ld_entity' => 'person', + 'json_ld_person_name' => 'Derice Bannock', + ]); + + $home = (new Cascade) + ->with($siteDefaults->all()) + ->withCurrent(Entry::findByUri('/')) + ->get(); + + $this->assertContains( + '{"@context":"https://schema.org","@type":"Person","name":"Derice Bannock","@id":"http://cool-runnings.com#person","url":"http://cool-runnings.com"}', + $home['json_ld']->all() + ); + + $about = (new Cascade) + ->with($siteDefaults->all()) + ->withCurrent(Entry::findByUri('/about')) + ->get(); + + $this->assertEmpty($about['json_ld']->all()); + } + #[Test] public function it_parses_antlers_in_json_ld_schema_values() { diff --git a/tests/GraphQLTest.php b/tests/GraphQLTest.php index 66768f7c..825c2e2c 100644 --- a/tests/GraphQLTest.php +++ b/tests/GraphQLTest.php @@ -375,7 +375,7 @@ public function it_queries_for_entry_seo_json_ld() $query = <<<'GQL' { - entry(slug: "nectar") { + entry(slug: "home") { seo { json_ld } diff --git a/tests/Localized/CascadeTest.php b/tests/Localized/CascadeTest.php index 476f2c05..3a88bf3d 100644 --- a/tests/Localized/CascadeTest.php +++ b/tests/Localized/CascadeTest.php @@ -90,4 +90,33 @@ public function it_generates_json_ld_breadcrumbs_for_entry_using_title_from_orig $this->assertEquals('About', $lastItem['name']); $this->assertEquals('http://cool-runnings.com/fr/about', $lastItem['item']); } + + #[Test] + public function it_only_outputs_organization_schema_on_each_sites_homepage() + { + $siteDefaults = SiteDefaults::in('french')->set([ + 'json_ld_entity' => 'organization', + 'json_ld_organization_name' => 'Cool Runnings Ltd', + ]); + + $this->get('http://cool-runnings.com/fr'); + + $home = (new Cascade) + ->with($siteDefaults->all()) + ->get(); + + $this->assertContains( + '{"@context":"https://schema.org","@type":"Organization","name":"Cool Runnings Ltd","@id":"http://cool-runnings.com/fr#organization","url":"http://cool-runnings.com/fr"}', + $home['json_ld']->all() + ); + + $this->get('http://cool-runnings.com/fr/about'); + + $about = (new Cascade) + ->with($siteDefaults->all()) + ->withCurrent(Entry::findByUri('/about', 'french')->entry()) + ->get(); + + $this->assertEmpty($about['json_ld']->all()); + } }