openvibers/openvibe.media Commits
An OpenVibe.Video upload's page on Media is noindex (its page is on openvibe.video) (#304)
Changes
@@@ -71,15 +71,20 @@ function isAiClip(kind, record) {return kind === 'clip' && !!Number(record.auto_generated || 0);}++// Apps whose items have their own watch page on another site: Live's recordings and clips (OpenVibe.Video's /v and++// /c), and OpenVibe.Video's uploads (app media-hub: /u/vup_…, an id only MediaHub knows). Media's page for one of them++// never competes with it in search (SEO audit 11-03: upload 6155 was indexable here and on openvibe.video).++const PAGES_ELSEWHERE = new Set(['live', 'media-hub']);++/*** May search engines index this watch page? Only when it is public, Media is its canonical home (the-- * owning app is not Live, whose items are canonical on OpenVibe.Video), and a person made it: AI clips-- * are noindex, as on Live. The sitemap lists exactly these pages (server/public/crawl.js).++ * owning app has no watch page of its own: PAGES_ELSEWHERE), and a person made it: AI clips are noindex,++ * as on Live. The sitemap lists exactly these pages (server/public/crawl.js).*/function watchIndexable(kind, record) {const visibility = record.visibility || (record.is_public ? 'public' : 'private');-- const ownedByLive = (record.app_id || 'live') === 'live';-- return visibility === 'public' && !ownedByLive && !isAiClip(kind, record);++ const pageElsewhere = PAGES_ELSEWHERE.has(record.app_id || 'live');++ return visibility === 'public' && !pageElsewhere && !isAiClip(kind, record);}/**@@@ -77,6 +77,11 @@ const http = require('http');assert.ok(other.includes('<meta name="robots" content="index, follow">'));const unlisted = pages.renderWatchPage('clip', { ...vod, id: 8, app_id: 'games', visibility: 'unlisted' });assert.ok(unlisted.includes('content="noindex, follow"'), 'unlisted never indexes');++ // An OpenVibe.Video upload (app media-hub) has its own page there (/u/vup_…): Media's never competes with it (SEO 11-03).++ const upload = pages.renderWatchPage('vod', { ...vod, id: 9, app_id: 'media-hub', title: 'SAGE WHEEL' });++ assert.ok(upload.includes('<meta name="robots" content="noindex, follow">'), 'an upload is not indexed on Media');++ assert.strictEqual(pages.watchIndexable('vod', { app_id: 'media-hub', visibility: 'public' }), false);++ assert.strictEqual(pages.watchIndexable('vod', { app_id: 'games', visibility: 'public' }), true, 'another app\'s public item still is');// The AI summary (openvibe-shared/seo pageSummary) on public watch pages: description, canonical, facts.assert.ok(html.includes('<meta name="ai-summary" content="We built a thing & it worked.">'), 'the watch page carries the AI summary');assert.ok(html.includes('<li>Duration: 1:02:05</li>') && html.includes('<li>Views: 1,234</li>'), 'with its facts');
@@ -71,15 +71,20 @@ function isAiClip(kind, record) {
@@ -71,15 +71,20 @@ function isAiClip(kind, record) {
return kind === 'clip' && !!Number(record.auto_generated || 0);
return kind === 'clip' && !!Number(record.auto_generated || 0);
}
}
+// Apps whose items have their own watch page on another site: Live's recordings and clips (OpenVibe.Video's /v and
+// /c), and OpenVibe.Video's uploads (app media-hub: /u/vup_…, an id only MediaHub knows). Media's page for one of them
+// never competes with it in search (SEO audit 11-03: upload 6155 was indexable here and on openvibe.video).
+const PAGES_ELSEWHERE = new Set(['live', 'media-hub']);
+
/**
/**
* May search engines index this watch page? Only when it is public, Media is its canonical home (the
* May search engines index this watch page? Only when it is public, Media is its canonical home (the
- * owning app is not Live, whose items are canonical on OpenVibe.Video), and a person made it: AI clips
- * are noindex, as on Live. The sitemap lists exactly these pages (server/public/crawl.js).
+ * owning app has no watch page of its own: PAGES_ELSEWHERE), and a person made it: AI clips are noindex,
+ * as on Live. The sitemap lists exactly these pages (server/public/crawl.js).
*/
*/
function watchIndexable(kind, record) {
function watchIndexable(kind, record) {
const visibility = record.visibility || (record.is_public ? 'public' : 'private');
const visibility = record.visibility || (record.is_public ? 'public' : 'private');
- const ownedByLive = (record.app_id || 'live') === 'live';
- return visibility === 'public' && !ownedByLive && !isAiClip(kind, record);
+ const pageElsewhere = PAGES_ELSEWHERE.has(record.app_id || 'live');
+ return visibility === 'public' && !pageElsewhere && !isAiClip(kind, record);
}
}
/**
/**
@@ -77,6 +77,11 @@ const http = require('http');
@@ -77,6 +77,11 @@ const http = require('http');
assert.ok(other.includes('<meta name="robots" content="index, follow">'));
assert.ok(other.includes('<meta name="robots" content="index, follow">'));
const unlisted = pages.renderWatchPage('clip', { ...vod, id: 8, app_id: 'games', visibility: 'unlisted' });
const unlisted = pages.renderWatchPage('clip', { ...vod, id: 8, app_id: 'games', visibility: 'unlisted' });
assert.ok(unlisted.includes('content="noindex, follow"'), 'unlisted never indexes');
assert.ok(unlisted.includes('content="noindex, follow"'), 'unlisted never indexes');
+ // An OpenVibe.Video upload (app media-hub) has its own page there (/u/vup_…): Media's never competes with it (SEO 11-03).
+ const upload = pages.renderWatchPage('vod', { ...vod, id: 9, app_id: 'media-hub', title: 'SAGE WHEEL' });
+ assert.ok(upload.includes('<meta name="robots" content="noindex, follow">'), 'an upload is not indexed on Media');
+ assert.strictEqual(pages.watchIndexable('vod', { app_id: 'media-hub', visibility: 'public' }), false);
+ assert.strictEqual(pages.watchIndexable('vod', { app_id: 'games', visibility: 'public' }), true, 'another app\'s public item still is');
// The AI summary (openvibe-shared/seo pageSummary) on public watch pages: description, canonical, facts.
// The AI summary (openvibe-shared/seo pageSummary) on public watch pages: description, canonical, facts.
assert.ok(html.includes('<meta name="ai-summary" content="We built a thing & it worked.">'), 'the watch page carries the AI summary');
assert.ok(html.includes('<meta name="ai-summary" content="We built a thing & it worked.">'), 'the watch page carries the AI summary');
assert.ok(html.includes('<li>Duration: 1:02:05</li>') && html.includes('<li>Views: 1,234</li>'), 'with its facts');
assert.ok(html.includes('<li>Duration: 1:02:05</li>') && html.includes('<li>Views: 1,234</li>'), 'with its facts');