Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(seo improvements): copy change for google serp preview #26410

Merged
merged 7 commits into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -156,27 +156,32 @@ export const socialMediaTiles: Record<SEO_MEDIA_TYPES, SocialMediaOption> = {
[SEO_MEDIA_TYPES.FACEBOOK]: {
label: 'Facebook',
value: SEO_MEDIA_TYPES.FACEBOOK,
icon: 'pi pi-facebook'
icon: 'pi pi-facebook',
description: 'seo.rules.media.preview.tile'
},
[SEO_MEDIA_TYPES.TWITTER]: {
label: 'X (Formerly Twitter)',
value: SEO_MEDIA_TYPES.TWITTER,
icon: 'pi pi-twitter'
icon: 'pi pi-twitter',
description: 'seo.rules.media.preview.tile'
},
[SEO_MEDIA_TYPES.LINKEDIN]: {
label: 'Linkedin',
value: SEO_MEDIA_TYPES.LINKEDIN,
icon: 'pi pi-linkedin'
icon: 'pi pi-linkedin',
description: 'seo.rules.media.preview.tile'
},
[SEO_MEDIA_TYPES.GOOGLE]: {
label: 'Google',
value: SEO_MEDIA_TYPES.GOOGLE,
icon: 'pi pi-google'
icon: 'pi pi-google',
description: 'seo.rules.media.search.engine'
}
};

export interface SocialMediaOption {
label: string;
value: SEO_MEDIA_TYPES;
icon: string;
description: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ describe('DotSetMetaTagsService', () => {
'seo.rules.og-description.found':
'og:description meta tag with valid content found!',
'seo.rules.description.more.one.found':
'More than 1 Meta Description found!'
'More than 1 Meta Description found!',
'seo.rules.og-description.description.not.found':
'og:description meta tag, and Meta Description not found!'
})
},
DotUploadService
Expand Down Expand Up @@ -266,4 +268,19 @@ describe('DotSetMetaTagsService', () => {
done();
});
});

it('should og:description meta tag, and Meta Description not found!', (done) => {
const testDoc: Document = document.implementation.createDocument(
'http://www.w3.org/1999/xhtml',
'html',
null
);

service.getMetaTagsResults(testDoc).subscribe((value) => {
expect(value[5].items[0].message).toEqual(
'<code>og:description</code> meta tag, and Meta Description not found!'
);
done();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ export class DotSeoMetaTagsService {
private getOgDescriptionItems(metaTagsObject: SeoMetaTags): SeoRulesResult[] {
const result: SeoRulesResult[] = [];
const ogDescription = metaTagsObject['og:description'];
const description = metaTagsObject['description'];
const descriptionElements = metaTagsObject['descriptionElements'];
const descriptionOgElements = metaTagsObject['descriptionOgElements'];

if (descriptionOgElements?.length > 1) {
Expand All @@ -241,7 +243,22 @@ export class DotSeoMetaTagsService {
);
}

if (!ogDescription || descriptionOgElements.length === 0) {
if (
this.areAllFalsyOrEmpty([
ogDescription,
descriptionOgElements,
description,
descriptionElements
])
) {
result.push(
this.getErrorItem(
this.dotMessageService.get('seo.rules.og-description.description.not.found')
)
);
}

if (description && this.areAllFalsyOrEmpty([ogDescription, descriptionOgElements])) {
result.push(
this.getErrorItem(this.dotMessageService.get('seo.rules.og-description.not.found'))
);
Expand Down Expand Up @@ -391,7 +408,7 @@ export class DotSeoMetaTagsService {

if (titleOgElements?.length >= 1 && this.areAllFalsyOrEmpty([titleOg])) {
result.push(
this.getErrorItem(this.dotMessageService.get(' seo.rules.og-title.found.empty'))
this.getErrorItem(this.dotMessageService.get('seo.rules.og-title.found.empty'))
);
}

Expand Down Expand Up @@ -444,6 +461,14 @@ export class DotSeoMetaTagsService {
);
}

if (imageOgElements?.length >= 1 && this.areAllFalsyOrEmpty([imageOg])) {
result.push(
this.getErrorItem(
this.dotMessageService.get('seo.rules.og-image.more.one.found.empty')
)
);
}

if (imageOgElements?.length > 1) {
result.push(
this.getErrorItem(
Expand Down Expand Up @@ -516,7 +541,9 @@ export class DotSeoMetaTagsService {

if (titleCardElements.length >= 1 && this.areAllFalsyOrEmpty([titleCard])) {
result.push(
this.getErrorItem(this.dotMessageService.get('seo.rules.twitter-card-title.empty'))
this.getErrorItem(
this.dotMessageService.get('seo.rules.twitter-card-title.found.empty')
)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@
alt="favicon" />
<span data-testId="page-hostName">{{ preview.hostName }}</span>
</div>
<a class="results-seo-tool__search-title">
<a
class="results-seo-tool__search-title"
data-testId="results-seo-tool-search-title">
{{ preview.title }}
</a>
<p class="results-seo-tool__search-description">
<p
class="results-seo-tool__search-description"
data-testId="results-seo-tool-search-description">
{{ preview.description }}
</p>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import { MockDotMessageService } from '@dotcms/utils-testing';
import { DotResultsSeoToolComponent } from './dot-results-seo-tool.component';
import { seoOGTagsMock, seoOGTagsResultMock, seoOGTagsResultOgMockTwitter } from './mocks';

import { SEO_MEDIA_TYPES } from '../../../content/services/dot-edit-content-html/models/meta-tags-model';
import {
SEO_MEDIA_TYPES,
SEO_LIMITS
} from '../../../content/services/dot-edit-content-html/models/meta-tags-model';
import { DotSeoMetaTagsService } from '../../../content/services/html/dot-seo-meta-tags.service';

describe('DotResultsSeoToolComponent', () => {
Expand Down Expand Up @@ -126,6 +129,18 @@ describe('DotResultsSeoToolComponent', () => {
});
});

it('should display title', () => {
const titleElement = spectator.query(byTestId('results-seo-tool-search-title'));
expect(titleElement.textContent).toContain(seoOGTagsMock.title);
expect(titleElement.textContent.length).toBeLessThan(SEO_LIMITS.MAX_TITLE_LENGTH);
});

it('should display description', () => {
const titleElement = spectator.query(byTestId('results-seo-tool-search-description'));
expect(titleElement.textContent).toContain(seoOGTagsMock.description);
expect(titleElement.textContent.length).toBeLessThan(SEO_LIMITS.MAX_DESCRIPTION_LENGTH);
});

it('should display host Name', () => {
const hostName = spectator.query(byTestId('page-hostName'));
expect(hostName).toHaveText(spectator.component.hostName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,19 @@ export class DotResultsSeoToolComponent implements OnInit, OnChanges {
seoMediaTypes = SEO_MEDIA_TYPES;

ngOnInit() {
const title =
this.seoOGTags['og:title']?.slice(0, SEO_LIMITS.MAX_OG_TITLE_LENGTH) ||
this.seoOGTags.title?.slice(0, SEO_LIMITS.MAX_TITLE_LENGTH);

const description =
this.seoOGTags['og:description']?.slice(0, SEO_LIMITS.MAX_OG_DESCRIPTION_LENGTH) ||
this.seoOGTags.description?.slice(0, SEO_LIMITS.MAX_DESCRIPTION_LENGTH);

this.allPreview = [
{
hostName: this.hostName,
title: this.seoOGTags['og:title']?.slice(0, SEO_LIMITS.MAX_OG_TITLE_LENGTH),
description: this.seoOGTags.description,
title,
description,
type: 'Desktop',
isMobile: false,
image: this.seoOGTags['og:image'],
Expand All @@ -90,8 +98,8 @@ export class DotResultsSeoToolComponent implements OnInit, OnChanges {
},
{
hostName: this.hostName,
title: this.seoOGTags['og:title'],
description: this.seoOGTags.description,
title,
description,
type: 'Mobile',
isMobile: true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ <h5 class="dot-select-seo-tool__title" data-testId="select-seo-tool-title">
{{ socialMediaTiles[socialMedia]?.label }}
</h5>
<span class="dot-select-seo-tool__details" data-testId="select-seo-tool-details">{{
'seo.rules.media.preview.tile' | dm
socialMediaTiles[socialMedia]?.description | dm
}}</span>
</div>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ describe('DotSelectSeoToolComponent', () => {
{
provide: DotMessageService,
useValue: new MockDotMessageService({
'seo.rules.media.preview.tile': 'Social Media Preview Tile'
'seo.rules.media.preview.tile': 'Social Media Preview Tile',
'seo.rules.media.search.engine': 'Search Engine Results Page'
})
}
],
Expand Down Expand Up @@ -44,6 +45,20 @@ describe('DotSelectSeoToolComponent', () => {
);
});

it('should display social media preview tile when socialMedia input is provided', () => {
spectator.setInput({
socialMedia: SEO_MEDIA_TYPES.GOOGLE
});
spectator.detectChanges();

expect(spectator.query(byTestId('select-seo-tool-item'))).toExist();
expect(spectator.query(byTestId('select-seo-tool-icon'))).toHaveClass('pi-google');
expect(spectator.query(byTestId('select-seo-tool-title'))).toHaveText('Google');
expect(spectator.query(byTestId('select-seo-tool-details'))).toHaveText(
'Search Engine Results Page'
);
});

it('should display device preview tile when device input is provided', () => {
spectator.setInput({
socialMedia: null
Expand Down
9 changes: 5 additions & 4 deletions dotCMS/src/main/webapp/WEB-INF/messages/Language.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5439,7 +5439,8 @@ seo.rules.description.greater=Meta Description found!
seo.rules.og-description.more.one.found=more than 1 og:description meta tag found!
seo.rules.og-description.found.empty=og:description meta tag found, but is empty!
seo.rules.og-description.not.found=og:description meta tag not found! Showing Meta Description instead.
seo.rules.og-description.greater=Meta Description found, but it has more than 160 characters.
seo.rules.og-description.description.not.found=og:description meta tag, and Meta Description not found!
seo.rules.og-description.greater=og:description meta tag found, but it has more than 160 characters.
seo.rules.og-description.less=og:description meta tag found, but has fewer than 55 characters of content.
seo.rules.og-description.found=og:description meta tag with valid content found!

Expand Down Expand Up @@ -5476,12 +5477,11 @@ seo.rules.twitter-card.found=twitter:card meta tag found!

seo.rules.twitter-card-title.not.found=twitter:title meta tag not found! Showing HTML Title instead.
seo.rules.twitter-card-title.more.one.found=more than 1 twitter:title meta tag found!
seo.rules.twitter-card-title.more.one.found.empty=twitter:title meta tag found, but is empty!
seo.rules.twitter-card-title.found.empty=twitter:title meta tag found, but is empty!
seo.rules.twitter-card.title.greater=twitter:title meta tag found, but has more than 70 characters.
seo.rules.twitter-card.title.less=twitter:title meta tag found, but has fewer than 30 characters of content.
seo.rules.twitter-card-title.found=twitter:title meta tag with valid content found!


seo.rules.twitter-card-description.not.found=twitter:description meta tag not found! Showing Description instead.
seo.rules.twitter-card-description.more.one.found=more than 1 twitter:description meta tag found!
seo.rules.twitter-card-description.more.one.found.empty=twitter:description meta tag found, but is empty!
Expand Down Expand Up @@ -5516,7 +5516,7 @@ seo.rules.read-more.linkedin.learn=<span>Learn more about <span><a target="_blan
seo.rules.read-more.linkedin.meta=<span>Learn more about <span><a target="_blank" href="https://www.linkedin.com/pulse/meta-tags-getting-them-right-linkedin-evelyn-pei/">Meta Tags: Getting Them Right for LinkedIn</a>. <i class="pi pi-external-link"></i></span></span>
seo.rules.read-more.linkedin.summary=<span>Read more about social media tile <span><a target="_blank" href="https://blog.hootsuite.com/social-media-image-sizes-guide/">image sizes</a>. <i class="pi pi-external-link"></i></span></span>

seo.rules.read-more.google.favicons=Favicons should be <span><a target="_blank" href="https://favicon.io/">.ico files</a>. <i class="pi pi-external-link"></i></span>
seo.rules.read-more.google.favicons=<span>Favicons should be <span><a target="_blank" href="https://favicon.io/">.ico files</a>. <i class="pi pi-external-link"></i></span></span>
seo.rules.read-more.google.title=HTML Title content should be between 30 and 60 characters.
seo.rules.read-more.google.title.unique=HTML Title content should be unique per page across your site.
seo.rules.read-more.google.description=Meta Description tags should be under 160 characters.
Expand All @@ -5525,4 +5525,5 @@ seo.rules.read-more.google.meta-tags=<span><a target="_blank" href="https://ahre
seo.rules.read-more.google.meta-description=<span><a target="_blank" href="https://moz.com/learn/seo/meta-description">What Are Meta Descriptions And How to Write Them</a>. <i class="pi pi-external-link"></i></span>
seo.rules.read-more.google.image-sizes=<span>Read more about social media tile <span><a target="_blank" href="https://blog.hootsuite.com/social-media-image-sizes-guide/">image sizes</a>. <i class="pi pi-external-link"></i></span></span>

seo.rules.media.search.engine=Search Engine Results Page
seo.rules.media.preview.tile=Social Media Preview Tile