Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
After Running the Pen, hit the "Edit On Codepen" to see the demo.
Welcome to Annoto developers docs!
If you are a developer, IT expert or anybody interested in integrating Annoto into your website or platform you are in the right place!
For user guides and how to setup Annoto please head to our main docs site site.
The core of Annoto is the Widget, it integrates Annoto without influencing website layout, as an overlay on top of your existing video player. We recommend reading the Widget getting started docs in any case, even if your preferred solution is Annoto Player or our Kaltura Player Plugin.
If you are looking to integrate Annoto as a widget without influencing website layout, as an overlay on top your existing video player, you are in the right place :)
At the moment we support the following players:
FlowPlayer
H5P
HTML5
JwPlayer
Kaltura V2/V7
OpenEdx
Plyr
VideoJS
Vimeo
Wistia
YouTube
Page Embed
Custom Player
Simply add the following script:
And bootstrap Annoto with the desired Application configuration:
The code snippet below provides a quick start for:
Widget setup
How to provide media details metadata (such as title, description, custom identifier)
How to provide group (course) details (identifier, title, description). This allows to build site hierarchy of courses/channels/etc. Once provided the discussion is scoped to the group, allowing reuse of same video in multiple groups.
User SSO (Single Sign On) authentication.
Dynamically load/destroy the widget for SPA (Single page applications)
Annoto application exposes an API. To get access to the API use the "ready" event:
Annoto is compatible with all major evergreen browsers (Edge, Chrome, Mozilla, Safari).
Many aspects of the widget UI can be modified via CSS Variables.
To override the defaults simply use .annoto
CSS class selector. For Example:
The widget has different utility classes that are appended to the .annoto
class based on a situation. The styling can be modified using combinations of those classes. For example, the most common state is dark theme of the widget:
For dark theme styling but only when the player is in full screen:
Below is a list of the most useful utility classes:
Please notice in most cases nnc
prefix is used. but in some cases nn
is used instead.
The main colors used by the widget are: primary, secondary, tertiary, light, medium, dark, darkest, success, warning, notice, danger.
Each main color has variants for different effects: contrast, shade and tint
Some or all the colors can be modified.
If for example primary color is modified, please make sure to set all it's variants to appropriate values, a great helper tool by Ionic can be used to generate the variants: https://ionicframework.com/docs/theming/color-generator
Those are standard colors of third party, usually they do not need to be changed.
Those colors are different shades of grey used by the widget. Please notice, the main colors light, medium, dark and darkest are used for styling.
In most cases there is no need to change any of the steps.
Annoto widget is set as absolute
meaning it doesn't influence the website layout. By default the application is contained inside a single DIV that is appended to the BODY.
If you require different behavior, you can put the following DIV anywhere in your DOM:
Once this DIV element is present in the DOM, when Annoto.boot() is called, it would be detected automatically by Annoto and serve as container for the Annoto app.
This is especially useful if BODY is not your main scrollable layout.
As a rule of thumb always place the container in the same scrollable element as your video.
When the Annoto widget is closed a small Fab button with comments icon is positioned next to the player to allow users to open the widget.
In some cases you might want to implement your own open/close UI and functionality.
To hide the default Fab button set the to true:
Annoto Timeline allows users to spot points of interest. The timeline can be embedded in the player or it can be positioned below the player. Lets explore the timeline configuration options:
By default, the timeline will be positioned under the player:
If Annoto is integrated in a 3d party system that is taking the role of LTI Tool that processes the LTI messaging requests, Annoto still supports taking care of managing the outcomes reporting.
The above setup requires the below configurations.
Once setup, Annoto backend services will take care of always keeping the grades up to date, including retries (in case of LMS rate limiting).
During LtiResourceLinkRequest
the LMS (Platform) provides the following claims:
integrationKey
is provided by Annoto during setup.
Annoto providers ends users, advanced interaction with video content. In order to do it Annoto requires access to video player API. Before Annoto can perform any action it must obtain the media source and the duration of the media.
We already support a variety of widely used player types, and constantly adding new ones. If you are using a custom player or player we don't support yet, you have 2 options:
Annoto widget exposes api to subscribe to analytics events so that can be used in custom integrations, for example ingested and analyzed by custom BI systems.
The widget provides two types of events:
Discrete events of user actions such as submit a comment, vote, read a reply, click on timestamp, first video play, etc.
Video analytics events that provides details about the current and historical accumulated video consumption of the user.
Interactions events of user actions that provide details about interactions consumed and the results of the activity.
Single page applications dynamically add and remove DOM elements on a single webpage. To provide solution for the dynamic nature of the applications, the player has APIs to close the player when elements are removed, and to reload the player into new DOM elements:
While multiple players can be setup on a single page. The Widget can be loaded only to a single player at a time. The widget is managed by a singleton, each time one of the players calls loadWidget()
, the widget is loaded in that player.
For more details please refer to the .
The Annoto course dashboard can be embedded in any context as a web-component:
The Annoto course dashboard can be embedded in any context as a web-component. Simply add the following scripts:
The following stylesheet:
The course dashboard can now be embedded anywhere on the page using the html tag:
The dashboard supports various configuration options:
To authenticate a user using SSO, the component exposes the following methods:
Annoto is compatible with all major evergreen browsers (Edge, Chrome, Mozilla, Safari).
If you are looking for industry leading Video Player with dual synchronous video playback, advanced layout capabilities and the power of Annoto interactivity, you are in the right place :)
The player is officially available via CDN and npm.
Annoto works out of the box with not only HTML <script>
tag, but also with all major bundlers/packagers/builders, such as Browserify, WebPack, etc.
The package includes full typings and can be used in typescript/ES6/flow projects.
Annoto player is exposed as , meaning it offers compatibility with the most popular script loaders and can be imported as commonjs/amd/es6. If you are not using any standard loader the player will be exposed on window as global variables.
If you are using a javascript module loader such as RequireJS. Annoto exposes a standard . For example for requireJS:
The main player class is . After you have the player instance it can be used to load video sources, dynamically control Widget, get access to Widget API and much more.
The annotoPlayer() helper is available only for the CDN. When using the npm package, please use the AnnotoPlayer constructor directly (see below)
The simplest way to create a player is using the :
PlayerOptions extends VideoJS options, so all options supported by the videojs player can be used.
Annoto plugin integration for the Kaltura player
If you are using Kaltura Media Space or KAF (Kaltura integration inside LMSs), Annoto is a and can be enabled in your platform with a click of a button.
If you are using custom Kaltura player embed on your platform you are in the right place!
Kaltura player allows extending its functionality via an extensive plugin system. To simplify Annoto integration within the Kaltura player, we have developed a plugin that allows adding Annoto with a simple flashvars
configuration while allowing full customisation of the Annoto Widget.
For more information on the Kaltura player toolkit and plugins please refer to .
The integration of Annoto plugin consist of 3 simple steps:
Setup Annoto plugin in the Kaltura universal studio (KMC) or using custom javascript.
Add javascript to modify the configuration of the Widget to fit your needs.
(Optional) Implement Single Sign On (SSO) integration and use the widget API.
Please follow the steps below to setup the plugin:
Login to KMC at .
At the "Studio" choose your player.
Navigate to the plugins menu on the left panel:
Create a new plugin by pressing on the ‘Create New Plugin’ button and name it annoto
.
Naming the plugin "annoto" is mandatory (this is just how Kaltura works).
Define the following Configuration options:
iframeHTML5Js
:
customerKey
: eyJhbGciOiJ...
The customer key is provided by Annoto.
Specifying the customer key is optional and can be done at step.
If Annoto LTI is used, the customerKey is not required
If customerKey is not provided, Annoto Will load in Demo Mode.
Demo Mode allows you to try out the product but all comments created are not saved after page refresh.
Save the player settings.
If you are using a javascript module loader such as RequireJS. Annoto exposes a standard . For example for requireJS:
Annoto application providers flexibility in how it integrates in the website. For full configuration options, please refer to the . Annoto API Typescript interfaces is available via the .
For full documentation, please refer to the .
For more elaborate example of api usage, please refer to the .
To show/hide the widget, use the . For more details on how to obtain the api object please refer to .
If is true, the timeline will be positioned inside the controls of the player:
Annoto supports reporting grading to LMS (Learning Management System) using the .
For Backend Webhook setup please refer to for details.
Those claims need to be provided to the :
Implement a and set it in . Contributions are very welcome and appreciated :)
, we are happy to help.
To listen to the events use the familiar api.
For more details on the event callback please refer to the interface. For full list of event types, please refer to .
For more details on the event callback please refer to the definition.
For more details on the event callback please refer to the definition.
It's built using .
The dashboard web-component is built using StencilJS. Please refer to the official docs on more information on how web-components built using StencilJS can be integrated and used:
'token' is same JWT token that is used for widget SSO. For more information please refer to .
The Player instance can be created using the constructor which allows the most flexibility:
Annoto Player extends standard with some advanced functionality, for more details, please refer to the .
The most common widget related api is available directly via the instance, for example: setupWidget, loadWidget, destroyWidget
.
For more advanced usages the can be obtained using await player.getWidgetApi()
The most recomended wait is to provide the User's SSO token to the widget configuration as show in .
An alternative way is to authenticate the user dynamically
Utility Class
Description
nnc-dark-theme
Used it different cases such as when widget is an overlay inside the player, player is in full screen, or configured as the default theme in the widget configuration.
nn-player-fs
Added when player is in full screen
nnc-mobile
Added when the user uses a mobile device, and the widget applies UX for mobile devices.
nn-is-open
Widget is in open state.
nn-[PAGE]-page
Changed based on the view the widget is showing. Common views:
nn-notes-page
nn-comments-page
nn-preferences-page
nnc-rtl
Widget has Right to Left layout.
In Customise Annoto Widget configuration we have learned how to listen to Kaltura player events and get access to the widget configuration and the API:
The annotoApi
can be used to accomplish various tasks such as dynamically hide/show the widget, load new configuration and maybe the most common task to perform Single Sign On (SSO) authentication:
For more information regarding SSO, please refer to the Annoto SSO Technical Guide or contact us at support@annoto.net.
The Annoto Widget is loaded inside the wistia player iframe so direct access to the Widget API and configuration is not possible.
Luckily we provide a helper script that exposes API to configure the widget and perform API actions.
Under the hood, we use postMessage for communicating with the widget in the Iframe.
The Iframe Client API requires the Wistia player Iframe embed element as constructor argument: new AnnotoIframeApi.Client(document.getElementById("wistia-player-id"))
annoto.onSetup()
provides opportunity to config set the Widget Configuration, for example configure the clientId
(Annoto API key).
Once configuration object is ready, call next(config)
to bootstrap the widget inside the Wistia player iframe.
config.widgets[0].player.type and element
are setup for Wistia internally by the plugin.
If player configuration callbacks are provided:
config.widgets[0].player.mediaDetails()
config.widget[0].player.mediaSrc()
They are called synchronously when next(config) is called. So the media details and the source should be already available at the time when next(config) is called.
The callbacks are called once during the setup.
It is NOT recommended to use theconfig.widget[0].player.mediaSrc()
for the Wistia player plugin.
When the Annoto plugin is loaded by the Kaltura player, it triggers custom events that allows you to get access to the configuration and the API for full customisation and control of the widget.
To subscribe to Kaltura player events please use Kaltura player API:
For detailed information on the Kaltura player API, please refer to http://player.kaltura.com/docs/api
annotoPluginSetup
is triggered first by the Annoto plugin and provides opportunity to modify the Annoto widget configuration before the widget is bootstrapped.
Once the widget is bootstrapped by the plugin annotoPluginReady
is triggered and provides access to the Annoto API.
Below is an example of modifying some basic widget options:
config is already setup by the Kaltura Annoto plugin, so we need only to override the required configuration, such as clientId, getPageUrl hook, etc. DO NOT CHANGE THE PLAYER TYPE OR PLAYER ELEMENT CONFIG.
For the default widget configuration used by the plugin please refer to: https://github.com/Annoto/kaltura-plugin
The plugin exposes annotoPluginReady
event that provides access to the API for implementing the SSO functionality.
Advanced topic
In some cases you might not have the required configuration for the Annoto Widget when annotoPluginSetup
is triggered, or would want to postpone the bootstrap of the widget until some condition is met.
Until delayDoneCallback
is called, the widget won't be bootstrapped and annotoPluginReady
won't be triggered.
If doneCb is not called, the widget is not bootstrapped. This can be used to dynamically decide on which videos to load the annoto plugin.
The plugin method is only for the Wistia player Iframe embed, for regular embeds, please use the standard widget integration method (set player type to wistia
).
Wistia player allows extending its functionality via an extensive plugin system. To enable Annoto integration within the Wistia player Iframe embed we have developed a plugin that allows adding Annoto via simple configuration.
For more information on the Wistia player and plugins please refer to Wistia documentation.
The integration of Annoto plugin consist of 3 simple steps:
Setup Annoto plugin in the Wistia player embed code.
Add javascript to modify the configuration of the Widget to fit your needs.
(Optional) Implement Single Sign On (SSO) integration and use the widget API.
Wistia iframe embeds take the exact same JSON parameters as a Standard embed, but they must be properly URL-encoded using a bracket syntax.
To add the Annoto plugin, add the following URL query param to the iframe src:
For example an iframe embed may look something like that:
For more information please refer to Wistia docs.
The widget would not load in the Wistia player Iframe yet. The widget is bootstrapped and loaded once the setup is complete. Please read Customise Widget Configuration for more details.
Advanced topic
Please refer to Setup using Universal Studio (KMC) for the recommended setup method.
If setting up Annoto plugin via Kaltura universal studio is not possible, or simply if more customisation is required. It is possible to compile a custom Annoto plugin for the Kaltura player and add it to the player via Javascript.
Please notice, according to Kaltura documentation:
"Flashvar based resource includes will only work on relative paths. You should save absolute external resource URLs to your configuration file for them to work in your production players."
Annoto plugin is an open source and can be compiled into a single javascript file: https://github.com/Annoto/kaltura-plugin
In we've setup the Widget, similar to onSetup
hook the Iframe Client API provides onReady
hook. Once onReady
is called, Annoto API actions can be performed:
The api
can be used to accomplish various tasks such as dynamically hide/show the widget, load new configuration and maybe the most common task to perform Single Sign On (SSO) authentication as demonstrated above.
The api object provided by the Iframe Client annoto.onReady
has limited capabilities:
It does not support Promise based usage. It supports only callbacks.
It support only the following methods: auth, load, close, show, hide, registerOriginProvider, logout.
registerOriginProvider supports only getPageUrl.
For more information regarding SSO, please refer to the Annoto SSO Technical Guide or contact us at support@annoto.net.
A webhook is an HTTP request, triggered by an event in a source system and sent to a destination system, often with a payload of data. Webhooks are automated, in other words they are automatically sent out when their event is fired in the source system.
This provides a way for one system (the source) to "speak" (HTTP request) to another system (the destination) when an event occurs, and share information (request payload) about the event that occurred.
Annoto backend is the source and will send messages to the destination platform.
Annoto will include a secure signature in all the webhook requests so that the destination platform can verify that the webhook request was generated by Annoto, and not from some server acting like Annoto.
Since the signature is specific to each and every webhook request, it also helps to validate that the message wasn’t intercepted and modified by someone in between the destination and the source (i.e. Man-in-the-middle attack).
We will send webhook messages only to valid TLS 1.2 and up (Https) endpoint.
Each Webhook message will include a signature header:
X-Annoto-JWS
- A JSON Web Signature () signed using the Annoto .
The X-Annoto-JWS
signature is a JSON Web Signature (JWS) and has a detached payload. It is a string that looks like JWS_PROTECTED_HEADER..JWS_SIGNATURE
JSON Web Signature (JWS) represents content secured with digital signatures or Message Authentication Codes (MACs) using JSON-based [RFC7159] data structures. The JWS cryptographic mechanisms provide integrity protection for an arbitrary sequence of octets.
The signature generation works as follows:
Webhook message is generated (e.g LTI outcomes)
The payload is signed using one of the private keys from Anntoo's JSON Web Key Set (e.g. kid: PylK7Us1ntafSdT9RxJ3q
The JWS protected header will contain the following standard properties:
kid
- The key used to sign the request. This can be looked up in the JWKS
alg
- Will be RS256
The detached JWS will be added as the X-Annoto-JWS
header to the Webhook request.
The HTTP Request is sent using POST method to the Webhook destination endpoint.
To verify that a webhook did actually come from Annoto, you need to compare the JSON Web Signature (JWS) from the X-Annoto-JWS
header with the JSON body of the request:
Ensure the X-Annoto-JWS
header exists. If it doesn't exist, this request didn't come from Annoto.
Look up the Annoto JWKS at the URL provided by Annoto. This contains the public keys, and should have a kid that matches the kid of the JWS_PROTECTED_HEADER
Use a JWT library for your programming language to verify the body matches the signature.
To implement the verification, some languages may require you to build URL variant of Base64 Encode of the JWS Payload (the webhook body) in order to verify the JWS.
The JWS signature uses a detached payload, so it is of the form JWS_PROTECTED_HEADER..JWS_SIGNATURE
as per RFC the kid for an individual JWK is immutable, and therefore it is safe and recommended to cache individual JWK's by their kid indefinitely (a proper JWT library will probably do that for you).
Example libraries that support RFC-7797 and JWKS, and simplify verifying a JWS:
Webhook messages are POST
requests with JSON body:
Webhook messages JSON body:
Single Sign-On (SSO) is an authentication mechanism that allows users to access several applications with only one set of login credentials.
By enabling SSO for your Annoto widget, you become responsible for the authentication of your users: they get authenticated through your own login portal and can use Annoto services freely.
An unauthenticated user requests access to your site (post login details to your server).
Your server authenticates the user, The user gets authenticated using your own authentication and authorization process.
If the user access is granted, You create a secured JWT payload that contains information about the user, using any standard library.
The JWT token should be part of the login post answer (or some other query as you see fit).
Annoto will not save the user login session. The annotoAPI.auth(token)
should be called at each page load.
What you will get from Annoto:
Your clientID
A unique secret that will be used to sign JWT tokens.
THE SECRET MUST BE KEPT CONFIDENTIAL ON YOUR SERVERS.
JWT payload should contain the required user information, and be encoded (signed) using the provided SECRET.
The JWT token MUST be signed using HS256 algorithm.
The JWT payload should contain:
If email is not provided, email notifications for users won’t work.
There are libraries available for virtually any programming language.
For full API documentation, please refer to the .
Java:
Node.js:
.Net (C#):
Annoto supports managing the via third party LTI 1.3 Tool. Webhook serving as a proxy medium.
Your client side JS code should call the method to authenticate the user.
JWT’s full specification is available at
A good source is:
Property | Type | Description | Mandatory |
iss | string | issuer of the token (clientID provided by Annoto) | Yes |
exp | number | expiration timestamp in seconds. Indicating when the user login session expires. | Yes |
jti | number/string | unique identifier for the JWT. Equal to the unique identifier of your user. | Yes |
name | string | visible user name | Yes |
string | User email account | No |
photoUrl | url | publicly accessible url to user photo | No |
scope | string | scope indicating permissions of the user:
| No |
aud | url | audience of the token (http://annoto.net) | No |