Skip to content

Commit bb6150f

Browse files
[7.x] Adds Report Rules for Ideal Lengths of Title & Description (#443)
Co-authored-by: Duncan McClean <[email protected]>
1 parent bbbb42f commit bb6150f

File tree

7 files changed

+508
-1
lines changed

7 files changed

+508
-1
lines changed

config/seo-pro.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@
4848
'reports' => [
4949
'keep_recent' => 'all',
5050
'queue_chunk_size' => 1000,
51+
'title_length' => [
52+
'warn_min' => 30,
53+
'pass_max' => 60,
54+
'warn_max' => 70,
55+
],
56+
'meta_description_length' => [
57+
'warn_min' => 120,
58+
'pass_max' => 160,
59+
'warn_max' => 240,
60+
],
5161
],
5262

5363
];

lang/en/messages.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,26 @@
7373
'three_segment_urls_site' => 'Page URLs should be a maximum of 3 segments.',
7474
'three_segment_urls_page' => 'The URL should be a maximum of 3 segments.',
7575
'three_segment_urls_site_warning' => ':count page with more than 3 segments in URL.|:count pages with more than 3 segments in their URLs.',
76+
'title_length_actionable_pill' => 'Title',
77+
'title_length_site' => 'Title tags should be within the ideal length range.',
78+
'title_length_page' => 'Your title tag is too long.',
79+
'title_length_site_warning' => ':count page with title tag outside ideal length range.|:count pages with title tags outside ideal length range.',
80+
'title_length_site_failing' => ':count page with title tag that is too long or missing.|:count pages with title tags that are too long or missing.',
81+
'title_length_page_warning' => 'Title tag is :length characters (outside ideal range).',
82+
'title_length_page_failing_missing' => 'Title tag is missing.',
83+
'title_length_page_failing_too_short' => 'Title tag is :length characters. Ideal length is >= :min.',
84+
'title_length_page_failing_too_long' => 'Title tag is :length characters. Ideal length is < :max.',
85+
'title_length_page_passing' => 'Title tag is :length characters (ideal length).',
86+
'meta_description_length_actionable_pill' => 'Description',
87+
'meta_description_length_site' => 'Meta descriptions should be within the ideal length range.',
88+
'meta_description_length_page' => 'Your meta description is too long.',
89+
'meta_description_length_site_warning' => ':count page with meta description outside ideal length range.|:count pages with meta descriptions outside ideal length range.',
90+
'meta_description_length_site_failing' => ':count page with meta description that is too long or missing.|:count pages with meta descriptions that are too long or missing.',
91+
'meta_description_length_page_warning' => 'Meta description is :length characters (outside ideal range).',
92+
'meta_description_length_page_failing_missing' => 'Meta description is missing.',
93+
'meta_description_length_page_failing_too_short' => 'Meta description is :length characters. Ideal length is >= :min.',
94+
'meta_description_length_page_failing_too_long' => 'Meta description is :length characters. Ideal length is < :max.',
95+
'meta_description_length_page_passing' => 'Meta description is :length characters (ideal length).',
7696
],
7797

7898
];

resources/js/components/reporting/StatusIcon.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ defineProps({
1111
<span v-if="status === 'pending'" class="icon icon-circular-graph animation-spin" />
1212
<Icon name="checkmark" class="text-green-600" v-else-if="status === 'pass'" />
1313
<Icon name="x" class="text-red-500" v-else-if="status === 'fail'" />
14-
<Icon name="alert-circle" class="text-orange" v-else-if="status === 'warning'" />
14+
<Icon name="alert-warning-exclamation-mark" class="text-orange" v-else-if="status === 'warning'" />
1515
</div>
1616
</template>

src/Reporting/Report.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ class Report implements Arrayable, Jsonable
3232
public static $rules = [
3333
Rules\SiteName::class,
3434
Rules\UniqueTitleTag::class,
35+
Rules\IdealTitleLength::class,
3536
Rules\UniqueMetaDescription::class,
37+
Rules\IdealMetaDescriptionLength::class,
3638
Rules\NoUnderscoresInUrl::class,
3739
Rules\ThreeSegmentUrls::class,
3840
];
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
<?php
2+
3+
namespace Statamic\SeoPro\Reporting\Rules;
4+
5+
use Statamic\SeoPro\Reporting\Rule;
6+
7+
class IdealMetaDescriptionLength extends Rule
8+
{
9+
use Concerns\FailsWhenPagesDontPass;
10+
11+
protected $length;
12+
protected $warnings;
13+
14+
public function actionablePill()
15+
{
16+
return __('seo-pro::messages.rules.meta_description_length_actionable_pill');
17+
}
18+
19+
public function siteDescription()
20+
{
21+
return __('seo-pro::messages.rules.meta_description_length_site');
22+
}
23+
24+
public function pageDescription()
25+
{
26+
if (! isset($this->length) || $this->length === 0) {
27+
return __('seo-pro::messages.rules.meta_description_length_page_failing_missing');
28+
}
29+
30+
$warnMin = config('statamic.seo-pro.reports.meta_description_length.warn_min', 120);
31+
$warnMax = config('statamic.seo-pro.reports.meta_description_length.warn_max', 240);
32+
33+
if ($this->length < $warnMin) {
34+
return __('seo-pro::messages.rules.meta_description_length_page_failing_too_short', [
35+
'length' => $this->length,
36+
'min' => $warnMin,
37+
]);
38+
}
39+
40+
if ($this->length > $warnMax) {
41+
return __('seo-pro::messages.rules.meta_description_length_page_failing_too_long', [
42+
'length' => $this->length,
43+
'max' => $warnMax,
44+
]);
45+
}
46+
47+
return __('seo-pro::messages.rules.meta_description_length_page');
48+
}
49+
50+
public function siteFailingComment()
51+
{
52+
return trans_choice(
53+
'seo-pro::messages.rules.meta_description_length_site_failing',
54+
$this->failures,
55+
['count' => $this->failures]
56+
);
57+
}
58+
59+
public function processSite()
60+
{
61+
$this->failures = $this->warnings = 0;
62+
63+
$this->report->pages()->each(function ($page) {
64+
$rule = new static;
65+
66+
$rule
67+
->setPage($page)
68+
->setReport($this->report)
69+
->load($page->results()[$this->id()]);
70+
71+
$status = $rule->status();
72+
73+
if ($status === 'fail') {
74+
$this->failures++;
75+
} elseif ($status === 'warning') {
76+
$this->warnings++;
77+
}
78+
});
79+
}
80+
81+
public function siteStatus()
82+
{
83+
if ($this->failures > 0) {
84+
return 'fail';
85+
}
86+
87+
if ($this->warnings > 0) {
88+
return 'warning';
89+
}
90+
91+
return 'pass';
92+
}
93+
94+
public function saveSite()
95+
{
96+
return [
97+
'failures' => $this->failures,
98+
'warnings' => $this->warnings,
99+
];
100+
}
101+
102+
public function loadSite($data)
103+
{
104+
if (! $data) {
105+
return;
106+
}
107+
108+
$this->failures = $data['failures'] ?? 0;
109+
$this->warnings = $data['warnings'] ?? 0;
110+
}
111+
112+
public function pageFailingComment()
113+
{
114+
$warnMax = config('statamic.seo-pro.reports.meta_description_length.warn_max', 240);
115+
116+
if ($this->length === 0) {
117+
return __('seo-pro::messages.rules.meta_description_length_page_failing_missing');
118+
}
119+
120+
return __('seo-pro::messages.rules.meta_description_length_page_failing_too_long', [
121+
'length' => $this->length,
122+
'max' => $warnMax,
123+
]);
124+
}
125+
126+
public function pagePassingComment()
127+
{
128+
return __('seo-pro::messages.rules.meta_description_length_page_passing', ['length' => $this->length]);
129+
}
130+
131+
public function pageWarningComment()
132+
{
133+
return __('seo-pro::messages.rules.meta_description_length_page_warning', ['length' => $this->length]);
134+
}
135+
136+
public function siteWarningComment()
137+
{
138+
return trans_choice(
139+
'seo-pro::messages.rules.meta_description_length_site_warning',
140+
$this->warnings,
141+
['count' => $this->warnings]
142+
);
143+
}
144+
145+
public function processPage()
146+
{
147+
$this->length = strlen($this->page->get('description', ''));
148+
}
149+
150+
public function pageStatus()
151+
{
152+
$warnMin = config('statamic.seo-pro.reports.meta_description_length.warn_min', 120);
153+
$passMax = config('statamic.seo-pro.reports.meta_description_length.pass_max', 160);
154+
$warnMax = config('statamic.seo-pro.reports.meta_description_length.warn_max', 240);
155+
156+
if ($this->length === 0) {
157+
return 'fail';
158+
}
159+
160+
if ($this->length < $warnMin || ($this->length > $passMax && $this->length <= $warnMax)) {
161+
return 'warning';
162+
}
163+
164+
if ($this->length > $warnMax) {
165+
return 'fail';
166+
}
167+
168+
return 'pass';
169+
}
170+
171+
public function savePage()
172+
{
173+
return $this->length;
174+
}
175+
176+
public function loadPage($data)
177+
{
178+
$this->length = $data;
179+
}
180+
}

0 commit comments

Comments
 (0)