generated from adobe/aem-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 169
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MWPW-131747 - Support structured data API for Video SEO (#1065)
* Add seotech-video feature
- Loading branch information
Showing
7 changed files
with
140 additions
and
2 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# SEOTECH | ||
|
||
Collection of SEO-related features that use the SEOTECH service. | ||
For more details see [SEOTECH API](https://wiki.corp.adobe.com/display/seoteam/SEOTECH+API) (Corp Only). | ||
|
||
## Video | ||
|
||
This feature selects a video url from the page then queries the SEOTECH service for structured data. | ||
If a valid VideoObject is returned then it is appended to the head of the document as JSON-LD. | ||
|
||
Metadata Properties: | ||
|
||
- `seotech-video-url`: url for query sent to /getVideoObject | ||
|
||
Video Platforms: | ||
|
||
- YouTube: Supported | ||
- Adobe TV: WIP | ||
- BYO HTML5: TBD | ||
|
||
See [video-metadata](../../blocks/video-metadata/) if you need to define a specific VideoObject on your page. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
export const SEOTECH_API_URL_PROD = 'https://14257-seotech.adobeioruntime.net'; | ||
export const SEOTECH_API_URL_STAGE = 'https://14257-seotech-stage.adobeioruntime.net'; | ||
|
||
export function logError(msg) { | ||
window.lana?.log(`SEOTECH: ${msg}`, { | ||
debug: false, | ||
implicitSampleRate: 100, | ||
sampleRate: 100, | ||
tags: 'errorType=seotech', | ||
}); | ||
} | ||
|
||
export async function getVideoObject(url, seotechAPIUrl) { | ||
const videoUrl = new URL(url)?.href; | ||
const videoObjectUrl = `${seotechAPIUrl}/api/v1/web/seotech/getVideoObject?url=${videoUrl}`; | ||
const resp = await fetch(videoObjectUrl, { headers: { 'Content-Type': 'application/json' } }); | ||
const body = await resp?.json(); | ||
if (!resp.ok) { | ||
throw new Error(`Failed to fetch video: ${body?.error}`); | ||
} | ||
return body.videoObject; | ||
} | ||
|
||
export default async function appendVideoObjectScriptTag(url, { createTag, getConfig }) { | ||
const seotechAPIUrl = getConfig()?.env?.name === 'prod' | ||
? SEOTECH_API_URL_PROD : SEOTECH_API_URL_STAGE; | ||
try { | ||
const obj = await getVideoObject(url, seotechAPIUrl); | ||
const script = createTag('script', { type: 'application/ld+json' }, JSON.stringify(obj)); | ||
document.head.append(script); | ||
} catch (e) { | ||
logError(e.message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { expect } from '@esm-bundle/chai'; | ||
import { stub } from 'sinon'; | ||
import { waitForElement } from '../../helpers/waitfor.js'; | ||
|
||
import { getConfig, createTag } from '../../../libs/utils/utils.js'; | ||
import appendVideoObjectScriptTag from '../../../libs/features/seotech/seotech.js'; | ||
|
||
describe('seotech', () => { | ||
describe('appendVideoObjectScriptTag', () => { | ||
beforeEach(async () => { | ||
window.lana = { log: () => console.log('LANA NOT STUBBED!') }; | ||
}); | ||
afterEach(() => { | ||
window.fetch?.restore?.(); | ||
window.lana?.restore?.(); | ||
}); | ||
|
||
it('should not append JSON-LD if url is invalid', async () => { | ||
const lanaStub = stub(window.lana, 'log'); | ||
await appendVideoObjectScriptTag('', { getConfig, createTag }); | ||
expect(lanaStub.calledOnceWith('SEOTECH: Failed to construct \'URL\': Invalid URL')).to.be.true; | ||
}); | ||
|
||
it('should not append JSON-LD if url not found', async () => { | ||
const lanaStub = stub(window.lana, 'log'); | ||
const fetchStub = stub(window, 'fetch'); | ||
fetchStub.returns(Promise.resolve(Response.json( | ||
{ error: 'ERROR!' }, | ||
{ status: 400 }, | ||
))); | ||
await appendVideoObjectScriptTag('http://fake', { getConfig, createTag }); | ||
expect(fetchStub.calledOnceWith( | ||
'https://14257-seotech-stage.adobeioruntime.net/api/v1/web/seotech/getVideoObject?url=http://fake/', | ||
)).to.be.true; | ||
expect(lanaStub.calledOnceWith('SEOTECH: Failed to fetch video: ERROR!')).to.be.true; | ||
}); | ||
|
||
it('should append JSON-LD', async () => { | ||
const fetchStub = stub(window, 'fetch'); | ||
const expectedVideoObject = { | ||
'@context': 'http://schema.org', | ||
'@type': 'VideoObject', | ||
name: 'fake', | ||
}; | ||
fetchStub.returns(Promise.resolve(Response.json( | ||
{ videoObject: expectedVideoObject }, | ||
{ status: 200 }, | ||
))); | ||
await appendVideoObjectScriptTag('http://fake', { getConfig, createTag }); | ||
expect(fetchStub.calledOnceWith( | ||
'https://14257-seotech-stage.adobeioruntime.net/api/v1/web/seotech/getVideoObject?url=http://fake/', | ||
)).to.be.true; | ||
const el = await waitForElement('script[type="application/ld+json"]'); | ||
const obj = JSON.parse(el.text); | ||
expect(obj).to.deep.equal(expectedVideoObject); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<title>Document Title</title> | ||
<meta name="seotech-video-url" content="FAKE"> | ||
<link rel="icon" href="data:,"> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters