Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions config/seo-pro.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@
'reports' => [
'keep_recent' => 'all',
'queue_chunk_size' => 1000,
'title_length' => [
'warn_min' => 30,
'pass_max' => 60,
'warn_max' => 70,
],
'meta_description_length' => [
'warn_min' => 120,
'pass_max' => 160,
'warn_max' => 240,
],
],

];
18 changes: 18 additions & 0 deletions lang/en/messages.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,24 @@
'three_segment_urls_site' => 'Page URLs should be a maximum of 3 segments.',
'three_segment_urls_page' => 'The URL should be a maximum of 3 segments.',
'three_segment_urls_site_warning' => ':count page with more than 3 segments in URL.|:count pages with more than 3 segments in their URLs.',
'title_length_actionable_pill' => 'Title',
'title_length_site' => 'Title tags should be within the ideal length range.',
'title_length_page' => 'Your title tag is too long.',
'title_length_site_warning' => ':count page with title tag outside ideal length range.|:count pages with title tags outside ideal length range.',
'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.',
'title_length_page_warning' => 'Title tag is :length characters (outside ideal range).',
'title_length_page_failing_missing' => 'Title tag is missing.',
'title_length_page_failing_too_long' => 'Title tag is :length characters. Ideal length is < :max.',
'title_length_page_passing' => 'Title tag is :length characters (ideal length).',
'meta_description_length_actionable_pill' => 'Description',
'meta_description_length_site' => 'Meta descriptions should be within the ideal length range.',
'meta_description_length_page' => 'Your meta description is too long.',
'meta_description_length_site_warning' => ':count page with meta description outside ideal length range.|:count pages with meta descriptions outside ideal length range.',
'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.',
'meta_description_length_page_warning' => 'Meta description is :length characters (outside ideal range).',
'meta_description_length_page_failing_missing' => 'Meta description is missing.',
'meta_description_length_page_failing_too_long' => 'Meta description is :length characters. Ideal length is < :max.',
'meta_description_length_page_passing' => 'Meta description is :length characters (ideal length).',
],

];
2 changes: 1 addition & 1 deletion resources/js/components/reporting/StatusIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ defineProps({
<span v-if="status === 'pending'" class="icon icon-circular-graph animation-spin" />
<Icon name="checkmark" class="text-green-600" v-else-if="status === 'pass'" />
<Icon name="x" class="text-red-500" v-else-if="status === 'fail'" />
<Icon name="alert-circle" class="text-orange" v-else-if="status === 'warning'" />
<Icon name="alert-warning-exclamation-mark" class="text-orange" v-else-if="status === 'warning'" />
</div>
</template>
2 changes: 2 additions & 0 deletions src/Reporting/Report.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ class Report implements Arrayable, Jsonable
public static $rules = [
Rules\SiteName::class,
Rules\UniqueTitleTag::class,
Rules\IdealTitleLength::class,
Rules\UniqueMetaDescription::class,
Rules\IdealMetaDescriptionLength::class,
Rules\NoUnderscoresInUrl::class,
Rules\ThreeSegmentUrls::class,
];
Expand Down
176 changes: 176 additions & 0 deletions src/Reporting/Rules/IdealMetaDescriptionLength.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
<?php

namespace Statamic\SeoPro\Reporting\Rules;

use Statamic\SeoPro\Reporting\Rule;

class IdealMetaDescriptionLength extends Rule
{
use Concerns\FailsWhenPagesDontPass;

protected $length;
protected $warnings;

public function actionablePill()
{
return __('seo-pro::messages.rules.meta_description_length_actionable_pill');
}

public function siteDescription()
{
return __('seo-pro::messages.rules.meta_description_length_site');
}

public function pageDescription()
{
if (! isset($this->length) || $this->length === 0) {
return __('seo-pro::messages.rules.meta_description_length_page_failing_missing');
}

$config = config('statamic.seo-pro.reports.meta_description_length');
$warnMax = $config['warn_max'] ?? 240;

if ($this->length > $warnMax) {
return __('seo-pro::messages.rules.meta_description_length_page_failing_too_long', [
'length' => $this->length,
'max' => $warnMax,
]);
}

return __('seo-pro::messages.rules.meta_description_length_page');
}

public function siteFailingComment()
{
return trans_choice(
'seo-pro::messages.rules.meta_description_length_site_failing',
$this->failures,
['count' => $this->failures]
);
}

public function processSite()
{
$this->failures = $this->warnings = 0;

$this->report->pages()->each(function ($page) {
$rule = new static;
$rule
->setPage($page)
->setReport($this->report)
->load($page->results()[$this->id()]);

$status = $rule->status();
if ($status === 'fail') {
$this->failures++;
} elseif ($status === 'warning') {
$this->warnings++;
}
});
}

public function siteStatus()
{
if ($this->failures > 0) {
return 'fail';
}

if ($this->warnings > 0) {
return 'warning';
}

return 'pass';
}

public function saveSite()
{
return [
'failures' => $this->failures,
'warnings' => $this->warnings,
];
}

public function loadSite($data)
{
if (is_array($data)) {
$this->failures = $data['failures'] ?? 0;
$this->warnings = $data['warnings'] ?? 0;
} else {
// Legacy support: old format was just a count of failures
$this->failures = $data ?? 0;
$this->warnings = 0;
}
}

public function pageFailingComment()
{
$config = config('statamic.seo-pro.reports.meta_description_length');
$warnMax = $config['warn_max'] ?? 240;

if ($this->length === 0) {
return __('seo-pro::messages.rules.meta_description_length_page_failing_missing');
}

return __('seo-pro::messages.rules.meta_description_length_page_failing_too_long', [
'length' => $this->length,
'max' => $warnMax,
]);
}

public function pagePassingComment()
{
return __('seo-pro::messages.rules.meta_description_length_page_passing', ['length' => $this->length]);
}

public function pageWarningComment()
{
return __('seo-pro::messages.rules.meta_description_length_page_warning', ['length' => $this->length]);
}

public function siteWarningComment()
{
return trans_choice(
'seo-pro::messages.rules.meta_description_length_site_warning',
$this->warnings,
['count' => $this->warnings]
);
}

public function processPage()
{
$description = $this->page->get('description');
$this->length = $description ? mb_strlen($description) : 0;
}

public function pageStatus()
{
$config = config('statamic.seo-pro.reports.meta_description_length');
$warnMin = $config['warn_min'] ?? 120;
$passMax = $config['pass_max'] ?? 160;
$warnMax = $config['warn_max'] ?? 240;

if ($this->length === 0) {
return 'fail';
}

if ($this->length < $warnMin || ($this->length > $passMax && $this->length <= $warnMax)) {
return 'warning';
}

if ($this->length > $warnMax) {
return 'fail';
}

return 'pass';
}

public function savePage()
{
return $this->length;
}

public function loadPage($data)
{
$this->length = $data;
}
}
Loading
Loading