Extension API
The Extension API provides the ability to ‘extend’ the capability of the platform by creating your own custom annotation.
Steps to use Extension API
-
Located in the project editor view, click on the icon to open the widget library menu.
-
From here, click the HTML tab. This block of code contains all of the necessary scripts to get started. Editing the raw HTMLboiler-plate code gives you the freedom to build a custom extension or annotation tailored to your needs.
This example represents a good starting point:
<!doctype html>
<html>
<head>
<title></title>
<meta charset="utf-8"/>
<style type="text/css">
html, body { margin: 0; padding: 0 }
</style>
</head>
<body>
<!-- HTML code goes here -->
<script type="text/javascript" src="//d2qrdklrsxowl2.cloudfront.net/js/hapyak-iframe.js"></script>
<script type="text/javascript" src="//d2qrdklrsxowl2.cloudfront.net/js/hapyak.api.js"></script>
<script type="text/javascript">
(function () {
/*
Write your script code here
*/
hapyak.context.addEventListener('data', function (variables) {
/*
Access Environment variables here
*/
});
}());
</script>
</body>
</html>
Player object
Object: hapyak.context.player
Methods
play()
hapyak.context.player.play()
Plays the video.
pause()
hapyak.context.player.pause()
Pauses the video.
mute()
hapyak.context.player.mute()
Mutes the video.
unmute()
hapyak.context.player.unmute()
Unmutes the video.
volume()
hapyak.context.player.volume()
Passing no arguments to this function returns a number between 0 to 1 representing the current volume.
hapyak.context.player.volume(0.5)
Passing a number between 0-1 will set the volume of the player to that value.
addClass(classNames, selector)
hapyak.context.player.
Add CSS classes on the IFRAME annotation where:
classNames
(string or array) can be a single class e.gmyAwesomeClass
or an array of classes['class1', 'class2']
selector
(optional) is used to target an existing class, id, or DOM element on the player element and add the class(es) to that element. If a selector is not passed in, the class will be added to the parent div within the iframe.
Example
hapyak.context.player.addClass('myClass', 'div#wrapper > h1)
removeClass(classNames, selector)
hapyak.context.player.
Remove CSS classes on the IFRAME annotation where:
classNames
(string or array) can be a single class e.gmyAwesomeClass
or an array of classes['class1', 'class2']
selector
(optional) is used to target an existing class, id, or DOM element on the player element and add the class(es) to that element. If a selector is not passed in, the class will be added to the parent div within the iframe.
Example
hapyak.context.player.removeClass('myClass', 'div#wrapper > .video-title')
Properties
paused
READ ONLY
let playerPaused = hapyak.context.player.paused
Get whether video is paused or not.
duration
READ ONLY
const videoLength = hapyak.context.player.duration //duration in seconds
Returns video duration (unit: seconds).
currentTime
READ / WRITE
let currentTime = hapyak.context.player.currentTime //returns time in seconds
Can be used to Get current video time (unit: seconds).
hapyak.context.player.currentTime = 20 //will jump to 20 seconds
Can also be used to set the current time of the video (jump to time).
isEditMode
READ ONLY
hapyak.context.player.isEditMode
Returns true if the IFRAME is being displayed inside a Brightcove Interactivity editor.
isEditing
READ ONLY
hapyak.context.player.isEditing
Returns true if the IFRAME is currently being edited.
Annotation object
Methods
hapyak.context.releaseGate()
A gate restricts the progress of a viewer in the video, requiring that they interact with an annotation prior to continuing on. In the extension api, you must explicitly state when a gate is to be relased.
To set a gate, toggle the respective option in the edit tab on the annotation to y
as seen in these screenshots:
- If the IFRAME is set to be gated, calling this method will release that gate.
Properties
annotationData
READ ONLY
hapyak.context.annotationData
Returns list of current annotation's properties. From here we can gain access to group and project configuration elements, including group and project level css. It is good practice to maintain styling by adding your group and project level CSS to the extension. In order to return this object, you must wait for the annotation to load:
hapyak.context.addEventListener('annotationload', function(){
console.log("annotation Data", hapyak.context.annotationData)
});
width
READ / WRITE
hapyak.context.width = pixels
Sets or gets the width of the IFRAME element.
height
READ / WRITE
hapyak.context.height = pixels
Sets or gets the height of the IFRAME element.
Events
Events are accessed through event listeners on the hapyak.context object:
hapyak.context.addEventListener("event", function () {
//do something here
});
annotationload
hapyak.context.addEventListener("annotationload", function (data) {
console.log(data)
});
-
Emitted when the current annotation loads.
-
The object emitted by this event contains data related to the annotation, as well as group, and project configuration data.
{
top: "19.999999999999993%",
left: "20%",
width: "60%",
height: "60%",
duration: 3,
durationFormat: "seconds"
durationValue: 3
end: 6.2256
groupConfig: {gates: true, minWidth: "0", iframeTimeout: 30000}
height: "60%"
id: "iframe1560519550307"
left: "20%"
projectConfig: {css: "", title: "Extension API example"},
projectId: 284539
projectTrackId: 575497
start: 3.2256
startTimeFormat: "seconds"
startTimeValue: 3.2256
}
loadedmetadata
hapyak.context.addEventListener("loadedmetadata", function (data) {
console.log(data)
});
Emitted when the Brightcove Interactivity metadata has finished loading.
data
hapyak.context.addEventListener("data", function (data) {
console.log(data);
});
The 'data' event will fire anytime there is a change in the environment variables. This happens often. Below is an example of the object that is returned.
{
annotationIds: {1457229: true, 1457445: true, 1457474: true, 1457475: true}
annotationsLoaded: true
configuration: {gates: true, minWidth: "0", iframeTimeout: 30000,}
projectAnnotations: {1457229: {}, 1457445: {}, 1457474: {}, 1457475: {}}
projectConfig: {css: "", title: "Extension API example"}
projectId: 284539
projectName: "Extension API example"
}
iframeshow
hapyak.context.addEventListener("iframeshow", function () {
console.log('Iframe has appeared');
});
Emitted when the IFRAME annotation enters its start time and is shown.
iframehide
hapyak.context.addEventListener("iframehide", function () {
console.log('Iframe annotation is no longer visible');
});
Emitted when the IFRAME annotation passes its end time and is hidden.
timeupdate
hapyak.context.addEventListener("timeupdate", function () {
// prints current time of video to the console
console.log(hapyak.context.player.currentTime);
});
Emitted when the current video time changes, and at a regular interval while the video is playing.
resized
hapyak.context.addEventListener("resized", function () {
console.log('Player is becoming smaller');
});
Emitted when the player is resized relative to the window.
play
hapyak.context.addEventListener("play", function () {
console.log("Video is currently playing");
});
Emitted when the video begins playing.
pause
hapyak.context.addEventListener("pause", function () {
console.log("Player has been paused");
});
Emitted when the video becomes paused.
editModeChange
hapyak.context.addEventListener("pause", function () {
console.log('Player has been paused');
});
Emitted when the edit mode is changed within the Brightcove Interactivity editor.
playerHover
hapyak.context.addEventListener("playerHover", function () {
console.log('Mouse is being hovered within the player');
});
Emitted when a hover event occurs over the player. This event as a returned value of true or false for hovering or not hovering respectively.
Tracking object
hapyak.context.tracking.widgetAction(action, properties)
Allows partners to track custom analytics.
trackButton.addEventListener( "click", function () {
hapyak.context.tracking.widgetAction('Follow', {'username': 'foobar123'});
});
- Action: The name of the action being tracked. This can be any string.
- Properties: Object of properties you wish to attach to this tracked action. The properties you wish to track is entirely up to you, but must be in true JSON format.
- using the VideoJS4 Embed type provided in the share modal, you can add options to the viewer object that will allow you to see, and track your own analytics as seen below:
<video id="hapyak-player-157199-8825" class="video-js vjs-default-skin" width="720" height="405" playsinline="playsinline">
<source src="https://sample.hapyak-hosted.com/group_uploads/23/16673/videos/862f7e32a9b94974b98f004ae49fa9ef/Sample-Video-with-sound.mp4" type="video/mp4"/>
</video>
<link rel="stylesheet" href="//vjs.zencdn.net/4.8/video-js.css">
<script type="text/javascript" src="//vjs.zencdn.net/4.8/video.js"></script>
<script type="text/javascript" src="//d2qrdklrsxowl2.cloudfront.net/js/hapyak.js"></script>
<script type="text/javascript">
(function () {
var vjs = videojs('hapyak-player-157199-8825');
hapyak.viewer({
apiKey: "12345678910111213",
projectId: 286041,
resetVariables: true,
player: vjs,
videoType: "html5",
playerType: "videojs4",
autoplay: false,
oncustomtrackingevent: function(data) {
console.log("custom Data", data)
}
});
})();
</script>
Session variables
These variables only exists during the session. Setting variables via the Extension API is functionally equivalent to passing in a "variables" object on the Viewer.
OBJECT: hapyak.context.env
Methods
set(name, value, temp, scope)
hapyak.context.env.set('obj', {name: "Andrew", anotherName: "Homer J Simpson"}, false, 'track');
Sets the value of the variable by name.
temp
if true, the value will not be captured to the browser local storage. (default: false)scope
should be set to track to make the data available to other annotations. (default: annotation scope)- Variables where
scope
isannotation scope
, there is no limitation to the data types that can be used.
Based on the example above, if we wanted to access the data from the the variable obj
we could do so in a text annotation like this:
The variable would resolve after the function is called:
get(name)
hapyak.context.env.get('name')
Returns the value of the variable by name
.
To return annotation data in current project:
hapyak.context.addEventListener("data", function() { //wait for data event to fire
hapyak.context.env.get('projectAnnotations')
})
Clears the value of a single variable by name
.
NOTES:
Any variables set with env.set are changed asynchronously because they need time to be communicated to the parent window. The new value will not be returned by env.get until the next "data" event fires, which should occur within a few milliseconds.
console.log(hapyak.context.env.get('myData')); //foo
hapyak.context.env.set('myData', 'bar');
console.log(hapyak.context.env.get('myData')); //foo
hapyak.context.addEventListener('data', function () {
console.log(hapyak.context.env.get('myData')); //bar
});