Writing Webtrends Infinity Tag Plugins

Configuring Plugins

Plugins can be configured on the Asset Coordination Service (ACS) context request in the configuration section similar to configuring Endpoints. Internal plugins are configured by creating an object with the key wt-plugins. In the wt-plugins object, add another object for each plugin that you would like enabled. In the plugin object, you can add any configuration values that are applicable to that plugin.

The ACS endpoint to use is in the Create Product Rule Definition section Acs Endpoints. For Product Context configuration options, see the ACS Object API.

Example of JSON payload ACS request for configuring One plugin – Facebook

For a full Analytics request example:

"config" : {
    "wt-plugins" : {
        "fb" : {
           //Any facebook config values
        }
    }
    ...   
  }

Example of JSON payload ACS request for configuring many plugins – Facebook, SEM, YouTube

"config" : {
    "wt-plugins" : {
        "fb" : {
           //Any facebook config values
        }, 
        "sem" : {
            //SEM config values
        }, 
        "yt": {
            //you tube config values
        }
    }
    ...   
  }

Example of JSON payload ACS request for configuring plugin with load configs

"config" : {
    "wt-plugins" : {
        "fb" : {
           "blockCollect":  true, // this will require the plugin call WT.ready()
           "timeout": 4200,
           "async": false,
        }
    }
    ...   
  }

Writing Plugins

Using this work flow and the API’s outlined in these documents:

  • Ensures a strong interface between the plugins and other functional components
  • Increases quality in code but also consistency in the the functionality Webtrends provides its customers

Prerequisites

  • Node v0.10.x
  • Maven 3 (Note: Maven may require you to install java; in this case use java7.)

Technical Description

There are both internal and external plugins. External plugins are plugins which are downloaded from a 1st or 3rd party locations. Internal plugins are inserted within the Analytics tag for performance reasons (this may change to meet evolving requirements).

Internal Plugin JS API

WT.regPlugin(pluginName, initCallback, config)

This is a manual collection event. This call allows internal Webtrends users to construct custom track calls. This contains no default data or configuration. The user must add the endpoint as shown below. For Webtrends Optimize®, this is a meaningless call since all tracking data goes on the Analytics track.

  • pluginName: Name of the plugin
  • initCallback: Callback to be executed upon initialization of all plugins
    • initCallback takes both a configuration object and ready function (e.g., initCallback(config, ready))
    • The configuration object contains plugin configuration and the ready function must be call if blockCollect is true
  • config {object}(optional) – Server settings override any configuration set here.
    • blockCollect: true means to block collection until ‘ready()’ is called. default: false
    • timeout: length of time until fail callback (default: 4000 ms)
    • async: true/false: true means it executes in its own setTimeout (default: true)
    • success: callback function for success (default: debug statement)
    • fail: callback function on failure (default: debug statement)

WT.common.pluginMgr.listPlugins();

This returns an object containing a list of the plugin configurations loaded. WT.common.pluginMgr must be initialized first for this call to be available.

Proposed Plugin Writing Workflow

Write your plugin. The plugin framework assumes the following structure for the plugin:

//
//  library type functionality for plugin
//
var someObject = function(){
    var self = this.
    console.log('declarative type logic here e.g. library functions referenced during runtime');

    self.printFoo = function(){
        console.log('foo');
    }
};

//
//  runtime type of logic 
//

// config:  corresponds to the 'customConfigs' below w/ server configs
// asyncReady:  signals in the blockCollect==true to countdown.  if blockCollect==false,
// then completion of this function will implicitly signal the countdown latch
var initCallback = function(config, asyncReady){
    console.log("initCallback");
    if(config["pluginSpecificConfig"]){
        console.log(config["pluginSpecificConfig"]);
    }
    var obj = new someObject();
    obj.printFoo();

    // Uncomment below if blockCollect===true
    // asyncReady();  //signals countdown latch to countdown
};

//
//  customConfigs
//

// This object is passed into the initCallback function along with configs passed
// along from the server
// Note:  these are overridden by server configs
var customConfigs = {
    "blockCollect":false,
    "timeout":420000,
    "pluginSpecificConfig":"someValue"
};

// register function
WT.regPlugin('nameOfPlugin', initCallback, customConfigs)

Assuming your plugin passes your unit test, use Fiddler to auto respond and inject your plugin into your analytics.js tag prior to the following statements:

WT.setExecuteState("analytics","ready");WT.fireEvent(new WT.Event(WT.Event.ANA_LOAD_COMPLETE,WT.Event.STATUS_SUCCESS),true);

Note: There may be updates to the analytics.js file, so make sure to download a fresh copy of analytics.js to use as the base for the auto-responder when inserting your plugin logic.

Write your unit tests for your plugin in qunit. This involves compiling the js via Grunt.

Config Object

When the plugin manager calls the plugin’s init function (initCallback in the above example), the first argument passed to the init function is a configuration object that looks something like this:

{
    async: true,
    blockFlag: false,
    config: {
        // Any plugin config values included in the JSON object used to generate the tag
    }
    // Etc
}

Plugin best practices

Please remember that these are guidelines.

  • Don’t pollute the global namespace. Instead of scoping your variables globally, scope them local to the closures and objects in which they are being used. Instead use WT namespace (e.g., WT.plugins.yt.someSpecialObject).
  • Write your plugin in testable manner. Always write a method or function with an idea of how it can be tested.
  • Do write unit tests. Writing JavaScript unit tests means that we can test in different browsers in a fast automated fashion. Further, it gives clues to subsequent developers on the functionality of a particular piece.
  • Write in a modular fashion. Write Javascript functions and plugins with an eye towards re-use and simplicity.
  • Having a clearly defined interface for your functionality. A clearly defined interface helps to show what a component is used for, creates modular components, and assists with creating unit tests.
  • Build using common features. When writing the component, be aware of what browser versions you expect it to run on, and what the capabilities of those browsers are. Choose common tools and techniques that will work across different browsers and versions.
  • Do browser sweeps. Test your plugin in different browsers.