Skip to content

Commit

Permalink
feat(FEC-13119): Add support for SEO (#1)
Browse files Browse the repository at this point in the history
solves FEC-13119, FEC-13135, FEC-13136

Add support for SEO
  • Loading branch information
JonathanTGold committed Jul 24, 2023
1 parent 834672e commit 2b393dd
Show file tree
Hide file tree
Showing 14 changed files with 458 additions and 113 deletions.
25 changes: 17 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
[![Build Status](https://app.travis-ci.com/kaltura/playkit-js-seo.svg?branch=master)](https://app.travis-ci.com/kaltura/playkit-js-seo)
[![Build Status](https://github.com/kaltura/playkit-js-seo/actions/workflows/run_canary_full_flow.yaml/badge.svg)](https://github.com/kaltura/playkit-js-seo/actions/workflows/run_canary_full_flow.yaml)
[![](https://img.shields.io/npm/v/@playkit-js/seo/latest.svg)](https://www.npmjs.com/package/@playkit-js/seo)
[![](https://img.shields.io/npm/v/@playkit-js/seo/canary.svg)](https://www.npmjs.com/package/@playkit-js/seo/v/canary)

# playkit-js-seo

playkit-js-seo is a [kaltura player] plugin that groups several UI services,
in order to simplify and facilitate the customization of the [kaltura player] UI by providing a simple and clean API.
**playkit-js-seo** is a [kaltura player] plugin that provides search engine optimization (SEO) capabilities for video content played by [kaltura player] SDK and managed in [Kaltura Management Console (KMC)].
It integrates structured data (Schema.org) into the player to improve discoverability and visibility of video content on search engines.

Each service manages a different area of UI functionality.
This plugin automatically generates structured data based on the video metadata, including properties such as
name, description, thumbnail URL, upload date, expiration date, duration, transcript, and chapters (if available). The structured data is then
either injected directly into the player or communicated to the parent frame if the player is embedded within an iframe.

It relies on [kaltura player] core API for managing UI features.
By incorporating structured data, the plugin helps search engines understand and interpret video content more effectively.
This can lead to improved SEO rankings and enhanced visibility in search engine results.

playkit-js-seo is written in [ECMAScript6] (`*.js`) and [TypeScript] (`*.ts`) (strongly typed superset of ES6),
and transpiled in ECMAScript5 using [Babel](https://babeljs.io/) and the [TypeScript compiler].
It relies on [kaltura player] core API for getting video metadata and listing for player events.

playkit-js-seo is written in [TypeScript] (`*.ts`) (strongly typed superset of ES6), and transpiled in ECMAScript5 using [Webpack].

[Webpack] is used to build the distro bundle and serve the local development environment.

[kaltura player]: https://github.com/kaltura/kaltura-player-js.
[Kaltura Management Console (KMC)]: https://corp.kaltura.com/resources/case-studies/kaltura-management-console-kmc-walkthrough/.
[ecmascript6]: https://github.com/ericdouglas/ES6-Learning#articles--tutorials
[typescript]: https://www.typescriptlang.org/
[typescript compiler]: https://www.typescriptlang.org/docs/handbook/compiler-options.html
[webpack]: https://webpack.js.org/

## Features

Write here your plugin description...
- Automatically generates structured data based on the video metadata, including properties such as
name, description, thumbnail URL, upload date, expiration date, duration, and content URL.
- The structured data is then
either injected directly into the player or communicated to the parent frame if the player is embedded within an iframe.


## Getting started with development

Expand Down
41 changes: 41 additions & 0 deletions demo/dev/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>SEO Plugin</title>
<script src="https://unpkg.com/@playkit-js/kaltura-player-js@canary/dist/kaltura-ovp-player.js"></script>
<script src="https://unpkg.com/@playkit-js/playkit-js-kaltura-cuepoints@canary/dist/playkit-kaltura-cuepoints.js"></script>
<script src="../../playkit-seo.js"></script>
</head>
<body>
<h1>Child(Player) Page</h1>
<div id="player-placeholder" style="width: 640px; height: 360px"></div>
<script>
const config = {
logLevel: 'DEBUG',
targetId: 'player-placeholder',
provider: {
partnerId: 1804331,
env: {
serviceUrl: 'https://cdnapisec.kaltura.com/api_v3'
}
},
playback: {
// In real scenario - preload mode should be automatically activated in studio
preload: 'auto'
},
plugins: {
seo: {
baseSegmentsUrl: 'https://www.example.com/example?t='
},
kalturaCuepoints: {}
}
};

const player = KalturaPlayer.setup(config);

player.loadMedia({ entryId: '1_r62g23gz' });
</script>
<a href="./parent.html">Parent(host) >>>></a>
</body>
</html>
19 changes: 19 additions & 0 deletions demo/dev/parent.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Parent-2 Page</title>
</head>
<body>
<h1>Parent(Player host) Page</h1>
<iframe id="myIframe" src="index.html" style="width: 640px; height: 460px"></iframe>

<script>
// Listen for messages from the iframe
window.addEventListener('message', (event) => {
if (event.data.type === 'SEOStructuredData') {
console.log(`Event ${event.data.type} fired in iframe:`, event.data);
}
});
</script>
</body>
</html>
32 changes: 0 additions & 32 deletions demo/index.html

This file was deleted.

40 changes: 40 additions & 0 deletions demo/prod/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>SEO Plugin</title>
<script src="https://unpkg.com/@playkit-js/kaltura-player-js@latest/dist/kaltura-ovp-player.js"></script>
<script src="https://unpkg.com/@playkit-js/playkit-js-kaltura-cuepoints@latest/dist/playkit-kaltura-cuepoints.js"></script>
<script src="https://unpkg.com/@playkit-js/playkit-js-seo@latest/dist/playkit-seo.js"></script>
</head>
<body>
<h1>Child(Player) Page</h1>
<div id="player-placeholder" style="width: 640px; height: 360px"></div>
<script>
const config = {
logLevel: 'DEBUG',
targetId: 'player-placeholder',
provider: {
partnerId: 1804331,
env: {
serviceUrl: 'https://cdnapisec.kaltura.com/api_v3'
}
},
playback: {
// In real scenario - preload mode should be automatically activated in studio
preload: 'auto'
},
plugins: {
seo: {
baseSegmentsUrl: 'https://www.example.com/example?t='
},
kalturaCuepoints: {}
}
};

const player = KalturaPlayer.setup(config);
player.loadMedia({ entryId: '1_r62g23gz' });
</script>
<a href="./parent.html">Parent(host) >>>></a>
</body>
</html>
19 changes: 19 additions & 0 deletions demo/prod/parent.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Parent-2 Page</title>
</head>
<body>
<h1>Parent(Player host) Page</h1>
<iframe id="myIframe" src="index.html" style="width: 640px; height: 460px"></iframe>

<script>
// Listen for messages from the iframe
window.addEventListener('message', (event) => {
if (event.data.type === 'SEOStructuredData') {
console.log(`Event ${event.data.type} fired in iframe:`, event);
}
});
</script>
</body>
</html>
10 changes: 3 additions & 7 deletions docs/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
First include `playkit-seo.js` **after** kaltura-player script in your web page.

```html
<script src="https://raw.githack.com/kaltura/kaltura-player-js/master/dist/kaltura-ovp-player.js"></script>
<script src="https://unpkg.com/@playkit-js/kaltura-player-js@latest/dist/kaltura-ovp-player.js"></script>
<script src="./playkit-seo.js"></script>
```

Expand All @@ -25,7 +25,7 @@ Add the seo to the player config under the plugins section.
partnerId: 1234567,
},
plugins: {
pluginExample: {},
seo: {},
}
};

Expand All @@ -34,18 +34,14 @@ const player = KalturaPlayer.setup(config);

### Configuration

You can see the **Example plugin** full configuration options [here](https://kaltura.github.io/playkit-js-seo/docs/api/<PATH-TO-YOUR-CONFIGURATION-DOC-FILE>)
You can see the **seo** full configuration options [here](https://kaltura.github.io/playkit-js-seo/docs/api/<PATH-TO-YOUR-CONFIGURATION-DOC-FILE>)

You can find configuration example [here](https://github.com/kaltura/playkit-js-seo/tree/master/demo/index.html)

## Full working example

You can find Full working example [here](https://github.com/kaltura/playkit-js-seo/tree/master/demo)

## API docs

[API docs](https://kaltura.github.io/playkit-js-seo/docs/api/index.html)

## Demo

[demo](https://kaltura.github.io/playkit-js-seo/demo/index.html)
17 changes: 12 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@
"dev": "npm run build:dev && webpack serve --open --mode development",
"build:dev": "webpack --mode development",
"build:prod": "webpack --mode production",
"build": "webpack --mode production",
"watch": "webpack --watch --mode development",
"test": "karma start --color --mode development",
"test:debug": "DEBUG_UNIT_TESTS=1 karma start karma.conf.js --auto-watch --no-single-run --browsers Chrome",
"test:watch": "karma start karma.conf.js --auto-watch --no-single-run",
"types:check": "tsc src/index.ts src/types/global.d.ts --jsx react --jsxFactory h --noEmit --target ESNext --moduleResolution node --experimentalDecorators --jsxFragmentFactory Fragment",
"types:check": "tsc src/index.ts --jsx react --jsxFactory h --noEmit --target ESNext --moduleResolution node --experimentalDecorators --jsxFragmentFactory Fragment",
"types:ganarate": "tsc src/index.ts src/types/global.d.ts --declaration --emitDeclarationOnly --outFile types/modules.ts --jsx react --jsxFactory h --jsxFragmentFactory Fragment --stripInternal true --target ESNext --moduleResolution node --experimentalDecorators",
"docs:ganarate": "typedoc",
"lint:check": "eslint src tests --ext .ts,.tsx,.js --color ",
Expand All @@ -44,21 +45,20 @@
"@babel/preset-env": "^7.17.10",
"@babel/preset-react": "^7.16.7",
"@babel/preset-typescript": "^7.16.7",
"@playkit-js/playkit-js-ui": "canary",
"@playkit-js/kaltura-player-js": "canary",
"@types/chai": "^4.3.3",
"@types/mocha": "^9.1.1",
"@types/node": "^14.11.2",
"@typescript-eslint/eslint-plugin": "^5.25.0",
"@typescript-eslint/parser": "^5.25.0",
"conventional-github-releaser": "3.1.3",
"babel-loader": "^8.2.4",
"chai": "^4.3.6",
"conventional-github-releaser": "3.1.3",
"css-loader": "^6.7.1",
"eslint": "^7.32.0",
"eslint-config-preact": "^1.3.0",
"eslint-plugin-mocha": "^10.1.0",
"eslint-plugin-prettier": "^4.0.0",
"@playkit-js/kaltura-player-js": "canary",
"karma": "^6.4.0",
"karma-chrome-launcher": "^3.1.1",
"karma-mocha": "^2.0.1",
Expand All @@ -70,6 +70,7 @@
"promise-polyfill": "^8.2.3",
"sass": "^1.52.1",
"sass-loader": "^13.0.0",
"schema-dts": "^1.1.2",
"sinon": "^14.0.0",
"standard-version": "^9.5.0",
"style-loader": "^3.3.1",
Expand All @@ -95,5 +96,11 @@
"Jonathan T. Gold",
"Gilad Nadav",
"Sivan Arganov"
]
],
"kaltura": {
"name": "seo",
"dependencies": {
"playkit-kaltura-cuepoints": "3.0.6"
}
}
}
29 changes: 29 additions & 0 deletions src/date-formaters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* @public
* @param {string} durationInSeconds - duration in Seconds
* @return {string} - The evaluated string
*/
export function convertDurationToISO8601(durationInSeconds: number): string {
const seconds = Math.floor(durationInSeconds % 60);
const minutes = Math.floor((durationInSeconds / 60) % 60);
const hours = Math.floor((durationInSeconds / (60 * 60)) % 24);
const days = Math.floor(durationInSeconds / (60 * 60 * 24));

const paddedHours = hours.toString().padStart(2, '0');
const paddedMinutes = minutes.toString().padStart(2, '0');

const isoDuration = `P${days || ''}DT${paddedHours}H${paddedMinutes}M${seconds}S`;
return isoDuration;
}

/**
* @public
* @param {string} unixTimestamp - date in Unix timestamp format
* @return {string} - The evaluated string in ISO 8601 format without the UTC offset
*/
export function convertUnixTimestampToISO8601(unixTimestamp: number): string {
const milliseconds = unixTimestamp * 1000;
const date = new Date(milliseconds);
const iso8601Date = date.toISOString().replace('.000Z', '+00:00');
return iso8601Date;
}
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { registerPlugin } from '@playkit-js/kaltura-player-js';
import { pluginName, Seo } from './seo';
import { PLUGIN_NAME, Seo } from './seo';

registerPlugin(pluginName, Seo);
registerPlugin(PLUGIN_NAME, Seo);

0 comments on commit 2b393dd

Please sign in to comment.