Techdocs

AMP Web SDK

AMP player

Creating Custom Plugins

This tutorial show the proper way to extend the player functionality by creating custom a plugin.

We will create a plugin for our fictional "Awesome Analytics". Awesome analytics will track:

  • Playback start, sending an analytics id
  • Playback finish, sending an analytics id and the stream duration.

To do so the plugin will use the function track from the fictional awe object:

function track( trackId, trackedInfo )

The steps required to create our custom plugin are:

  1. Creating a plugin object.
  2. Creating a factory function.
  3. Registering the factory function.
  4. Configuring our custom awesome analytics plugin.
  5. Loading a plugin script from an external file.
  6. Using the plugin.

1. Creating a plugin object

The only strict requirement for an AMP plugin is to include the config attribute. However it makes no sense having a plugin that only holds its own configuration. The plugin must implement as well any functions that will be used to expand the AMP functionality.

Following with our example we'll include two functions:

  • trackStart( )
  • trackEnd( duration )

So the Awesome Analytics plugin object will look like this:

function createPluginObject( config ) {
	return {
		config: config,
		trackStart : function( ) {
			this.config.awe.track( this.config.trackId, {} )
		},
		trackEnd : function( duration ) {
			this.config.awe.track( this.config.trackId, { duration : duration } )
		}
	}
}

Notice that since we defined that trackId will be part of our config object we can use it in our track functions.

2. Creating a factory function

In order to load any plugin AMP needs a factory function. The factory function will be called when it is time to create a new instance of the plugin. The factory function requires two arguments: The instance of the player and the configuration object for the plugin. Optionally, it can also receive a key.

function createAwePlugin( player, config, key ) {
	return new Promise( function ( resolve, reject ) {
		if ( config.awe && config.trackId ) {
			resolve( createPluginObject( config ) );
		} else {
			reject( "Config doesn't include awe object or track id" );
		}
	});
}

It's worth mentioning that steps 1 & 2 were split for the sake of clarity. However it is not mandatory to have it this way. It is ok to create the plugin object directly in the factory function. i.e:

function createAwePlugin( player, config, key ) {
	return new Promise( function ( resolve, reject ) {
		if ( config.awe && config.trackId ) {
			resolve( {
				config: config,
				trackStart : function( ) {
					this.config.awe.track( this.config.trackId, {} )
				},
				trackEnd : function( duration ) {
					this.config.awe.track( this.config.trackId, { duration : duration } )
				}
			} );
		} else {
			reject( "Config doesn't include awe object or track id" );
		}
	});
}

3. Registering the factory function

Even though the factory function is ready, currently, AMP doesn't know that "Awesome Analytics" exists. To make the awesome analytics plugin "visible" to AMP it's needed to register the factory function by calling the function registerPlugin and passing as arguments a key for the plugin and the factory function.

akamai.amp.AMP.registerPlugin( "awesomeanalytics", createAwePlugin);

4. Configuring Our Custom Awesome Analytics plugin.

Before continuing with this step, please check the akamai.amp.PluginConfig interface. The configuration that will be passed to our plugin should match this interface.

The minimum accepted configuration is a boolean. This will tell AMP to either enable or disable the plugin.

var config = {
	plugins: {
		awesomeanalytics: true
	}
};
akamai.amp.AMP.create("akamai-media-player", config);

It is important to notice that the plugin configuration section for "Awesome Analytics" matches the key used in step 3, therefore this key should follow the naming constraints of Java Script. As an example, the key = "123-Awe" cannot be used since the JS parser will be unable to parse it as a variable name.

Even though it is possible to create a plugin that only requires the enabled/dissabled boolean, in most real world applications more information is required. For "Awesome Analytics", as an example, the plugin still needs a reference to the "awe object" and a "trackId". So a more realistic configuration will look like:

var config = {
	plugins: {
		awesomeanalytics: {
			enabled: true,
			trackId: '783e35e2-d98e-11ea-87d0-0242ac130003',
			awe: static_awe
		}
	}
};
akamai.amp.AMP.create("akamai-media-player", config);

Finally we can skip the enabled flags since plugins are enabled by default. This leaves us with the following configuration:

var config = {
	plugins: {
		awesomeanalytics: {
			trackId: '783e35e2-d98e-11ea-87d0-0242ac130003',
			awe: static_awe
		}
	}
};
akamai.amp.AMP.create("akamai-media-player", config);

5. Loading a plugin script from an external file

More often than not, in a real world plugin implementation, the actual plugin is a complex piece of software that already lives in a separate JS script. This means that the AMP plugin will only work as a facade for the "real plugin". We can see this in our example. So far we've asumed that the static_awe object exists somewhere in our DOM, however, we haven't specified how it is loaded or handled.

AMP allows "AMP Plugins" to load any required script ( Usually the core of the plugin ) from an external file by using the attribute resources. At this point it is important to take a look at the following pages in our documentation:

The resource object should match the akamai.amp.Resource interface and include a src and type. Below there's an example of a resource object.

var config = {
	plugins: {
		awesomeanalytics: {
			resources: [
				{
					src: "//awesome_analytcss_server/awesomeanalytics.js", //url to my "real plugin script"
					type: "text/javascript" // JS type so it is load as an script
				}
			],
			trackId: '783e35e2-d98e-11ea-87d0-0242ac130003',
		}
	}
};
akamai.amp.AMP.create("akamai-media-player", config);

Since now the static_awe object will be available after awesomeanalytics.js is fully loaded, we can update our factory function and remove the awe object as part of the expected configuration. Here is the updated version:

function createAwePlugin( player, config, key ) {
	return new Promise( function ( resolve, reject ) {
		if ( static_awe && config.trackId ) {
			resolve( {
				config: config,
				trackStart : function( ) {
					static_awe.track( this.config.trackId, {} )
				},
				trackEnd : function( duration ) {
					static_awe.track( this.config.trackId, { duration : duration } )
				}
			} );
		} else {
			reject( "Config doesn't include track id or awesomeanalytics.js hasn't loaded yet" );
		}
	});
}

6. Using the Plugin

Now that we have successfuly loaded "awesomeanalytics.js" and created and registered our plugin, it is time to implement the plugin desired behaviour. To do so we'll add event listeners for the desired events. To know more about events please check akamai.amp.Events. Here is the example code:

akamai.amp.AMP.create("akamai-media-playeramps", config).then( function (amp) {
	amp.addEventListener(akamai.amp.Events.STARTED, (event) => {
		amp.awesomeanalytics.trackStart()
	});
	amp.addEventListener(akamai.amp.Events.ENDED, (event) => {
		amp.awesomeanalytics.trackEnd( amp.media.duration )
	});
});

Notice that we accessed our plugin by using the key awesomeanalytics (the one defined in step 3). As it can be seen in the example both functions trackStart and trackEnd are available.


Notes:

  • For convenience AMP provides a Plugin base class which contains common functionality such as event dispatching. Please check akamai.amp.Plugin.
  • further information on akamai.amp.Media.