Warning: Can't synchronize with the repository (Couldn't open Subversion repository /vol/svn/developer.metricly.com: SubversionException: ("Can't open file '/vol/svn/developer.metricly.com/format': Permission denied", 13)). Look in the Trac log for more information.

Plugin API Documentation


The Metricly Plug-In API or PAPI is in essence a reverse API. Unlike most API's where you are given a set of access points and rules for connecting and accessing or modifying data, your plug-in will act as an API that Metricly will connect to retrieve data from your system. We provide the rules for writing access points that Metricly will understand and allow you to integrate custom data sources that we currently do not support.

Getting Started

Once you're logged into Metricly visit the  Developer section. This is where you can see all your current plug-ins and create new ones.

To add a new plug-in scroll down to "Add a new Data Source Plug-in" and enter a new "Plug-in Name". This is a unique identifier and ideally is descriptive of your data source. All lowercase letters and numbers preferred but not required. The name cannot contain spaces but dashes and underscores are allowed. This cannot be changed once created so make sure you're happy with your name before proceeding. Next add a "Display Name" to your plug-in. This is what your users will see in the graphs and settings pages. Lastly select a general Category for your plug-in. This should describe the greater portion of the metrics you will be delivering stats for. Once you've filled in all 3 fields click 'Save' to continue.

Editing your plug-in

Once you've saved your plug-in you're taken to the edit screen where you can tell Metricly more about the plug-in you're creating.

From here you can edit your display name, category, description, endpoint, version and status as well as add a logo and grant access to companies to use your plug-in.

Once you create and register a plug-in with Metricly, you as the developer will see that plugin on the settings page for any company you have access to. Although unless you explicitly give the company permission or connect the plug-in you will be the only one to see it in the setings page.

Once you create your plugin you will have to set an 'endpoint'. The endpoint is where the Metricly Plug-in API (PAPI) will contact your plug-in and route all requests.

A typical endpoint will look something like:


You will also see your plug-ins API Key at the top of the page. This is a key that you will have to pass back with every request. If you're using the sample code you will need to add it in the settings.php file. Just fill in the empty PLUGIN_KEY definition and the tools will automatically use it.

Basic Plug-in Flow

Metricly PAPI Tools

Our sample plug-in ships with a file called metricly_papi_tools.php which contain several classes and functions to make your plug-in development much easier. Currently our sample plug-in is only available for PHP 5. We will be releasing more languages in the future.

When you instantiate the Metricly class it will automatically check to make sure all the proper post variables have been sent that are required to fulfill a request and do some basic clean up and decoding on them so they're fit for use right away.

Connection Process Overview

When a user wants to make a new connection with your plugin there are a few steps. We call your plugin enpoint with the 'connect' method. You then are responsible for gathering the appropriate credentials or unique identifiers for the user that will allow you to gather the data you need. You can do a form post back to your plug-in if it's user supplied or you can create an OAuth endpoint and pass the credentials that way.

Once you've gathered the credentials you will make a call to $metricly->registerConnection([STRING]) where STRING is a label that will identify the connection to the user in the Metricly settings page. Usually it's a user or company name.

More on calls to the Metricly object in the section Metricly PAPI Tools. We have pre-built convenience methods for you to use to make the process easier. Calling registerConnection will allocate a 'connection_id' on the system to identify this connection from this point forward.

Once you have a connection_id you can store the credentials on in the PAPI Data Store. All data that's stored in our database is encrypted using 256 bit Rijndael encryption protocol so it's safe even if somehow the database were ever to be compromised.

We require all access tokens to be stored in the PAPI Data Store. You retrieve them via a getData call when your plug-in is polled by Metricly for data.

Plug-ins must handle the following requests for interactions

When we send your plugin a request it will be keyed by a POST variable named 'method' with one of the following values.


Gets all available metrics that the plug-in provides for that user. This can be a static set or dynamically generated based on data source. Metrics must be returned as JSON with the Metrics in an array named 'data' and keyed on metric_id.

Post Variables

  • None


    "statusCode": "OK",
    "errorCode": 0,
    "errorMessage": "",
    "data": {
        "page_impressions": {
            "name": "Page impressions",
            "id": "page_impressions",
            "metric_id": "page_impressions",
            "metricly_name": "advertising\/impressions",
            "metric_long_description": "A page impression is generated every time a user views a page displaying Google ads.",
            "metric_description": "The total number of single-page impressions regardless of ad count.",
            "metric_type": "number",
            "dimension": "channel"
        "clicks": {
            "name": "Clicks",
            "id": "clicks",
            "metric_id": "clicks",
            "metricly_name": "advertising\/clicks",
            "metric_long_description": "The total number of clicks on a Google Adsense advertisement.",
            "metric_description": "The total number of clicks on a Google Adsense advertisement.",
            "metric_type": "number",
            "dimension": "channel"


Given a metric this returns any dimensions that can be calculated.

Post Variables

  • metric - the metric id from your metrics list


    "statusCode": "OK",
    "errorCode": 0,
    "errorMessage": "",
    "data": {
        "ga:browserVersion": {
            "name": "Browser Version",
            "id": "ga:browserVersion",
            "value_type": "discrete",
            "dimension_description": "The browser versions used by visitors to your website. For example,"
        "ga:city": {
            "name": "City",
            "id": "ga:city",
            "value_type": "discrete",
            "dimension_description": "The cities of website visitors, derived from IP addresses."


Given a dimension and metric the plug-in returns any values available for that dimension. The dimension values are returned as keys in the return array, and we use the cumulative value for that metric for the array value.

Post Variables

  • metric - the metric id
  • dimension - the dimension id


    "statusCode": "OK",
    "errorCode": 0,
    "errorMessage": "",
    "data": {
        "Australia": 326,
        "Austria": 76,
        "Azerbaijan": 7,
        "Botswana": 3,
        "United Kingdom": 984,
        "United States": 15222,
        "Yemen": 4,
        "Zambia": 2


Getdata takes the full suite of input from Metricly and returns the data based on those values.

Post Variables

  • metric- The metric id to return data for
  • subtotal_dimension - Subtotal the result set on this dimension id.
  • subtotal_type - Can be one of 3 items. 'top5', 'bottom5' or 'custom'. If custom the values will be in the subtotal_custom_choices variable as an array.
  • subtotal_custom_choices - If the subtotal_type is 'custom', this is a JSON array of the dimension values we want to subtotal.
  • filter_dimension - Limit the result set to just this dimension id (and the value will be set by 'filter_value'.
  • filter_operator - We currently only support the '=' operator.
  • filter_value - Limit the result set to just this value (where the 'filter_dimension' equals this 'value').
  • date_start - The earliest date for the data. Will be in the format of YYYY-MM-DD
  • date_end - The most recent date for the data. Will be in the format of YYYY-MM-DD

If you are using the PAPI tools in metricly_papi_tools.php these variables will be automatically set and cleaned for you when you instantiate the Metricly Class. They are also available as their short names ie: $metric and $date_start from your controller as well. See the Sample Plugin for implementation details.


Example return for data call with no dimensions. If no dimensions are present use M:ALL as the container for the return.

    "statusCode": "OK",
    "errorCode": 0,
    "errorMessage": "",
    "data": {
        "M:ALL": {
            "2010-03-03": 0,
            "2010-03-02": 1,
            "2010-03-01": 0,
            "2010-02-28": 0,
            "2010-02-27": 0,
            "2010-02-26": 0,
            "2010-02-25": 1

Example return for 4 dimension values. DIMENSION_VALUE_X should be the actual dimension name.

    "statusCode": "OK",
    "errorCode": 0,
    "errorMessage": "",
    "data": {
        "DIMENSION_VALUE_1": {
            "2010-02-22": 678,
            "2010-02-21": 667,
            "2010-02-20": 653,
            "2010-02-19": 698,
            "2010-02-18": 680,
            "2010-02-17": 687
        "DIMENSION_VALUE_2": {
            "2010-02-22": 202,
            "2010-02-21": 184,
            "2010-02-20": 129,
            "2010-02-19": 148,
            "2010-02-18": 214,
            "2010-02-17": 235
        "DIMENSION_VALUE_3": {
            "2010-02-22": 96,
            "2010-02-21": 61,
            "2010-02-20": 81,
            "2010-02-19": 141,
            "2010-02-18": 1238,
            "2010-02-17": 118
        "DIMENSION_VALUE_4": {
            "2010-02-22": 0,
            "2010-02-21": 0,
            "2010-02-20": 0,
            "2010-02-19": 0,
            "2010-02-18": 0,
            "2010-02-17": 0


The connect call is a different type of call from the previous data calls. It's a GET request that requires you to display HTML that will be viewed in an embedded iFrame on a users Settings page on Metricly.com.

This is where you will gather the users credentials that allow them to access your data. If this is an internal tool with no credentials then you can simply call the registerConnection method and assign the plugin a connection ID.


The config call is a GET request that requires you to return HTML that will be viewed in an embedded iFrame on a users Settings page on Metricly.com.


It's the responsibility of your plug-in to determine if the company we're passing has been connected to your plug-in. Typically this is done by sending a query for credentials to the Metricly PAPI data store. If the user is not connected the plug-in should then output HTML with instructions on how to connect. This usually has a link to an OAuth process or a form that submits back to your plug-in that verifies the credentials, stores them in the Metricly PAPI data store and sends a connection event to PAPI.

If the company is already connected to your plug-in and is ready to receive stats then you should display a settings connection form that posts back to your plug-in that saves the configuration options in the PAPI data store. Some plug-ins will not have any configuration options but will still be required to generate a settings page that informs the user that the plug-in is connected and that there are no configuration options for your plug-in.

GET Variables

The fields in the query string will always be present and consist of the following

  • user_id - The user_id of the person making the request.
  • company_id - The numerical company_id associated with the request.
  • security_key - This is a string that must be sent in concert with the user_id and company_id back to the PAPI for all operations such as connect, set and get data.


Since there are times when you're going to want to display a page for the user and have them submit information back to it or leave your plug-in to fulfill an OAuth token exchange while maintaining state the Metricly tools automatically store certain key values in a session for you. You are responsible for starting the session since some developers prefer to use non-standard session storage mechanisms such as database session storage we leave that up to you. If you are using a standard PHP install you can simply call a session_start(); at the beginning of your plugin.

The PAPI Data Store

Plug-ins will generally require a user to enter either login credentials or connect to a data source through an OAuth connection. If you are writing a plug-in for your own private use you may choose to bypass the configuration steps and store your credentials locally. Any plug-in that stores user credentials must be SSL compliant and use the PAPI Data Store excluseively before it can be authorized as a partner plug-in and opened to the Metricly audience.

The PAPI Data Store is a simple Key/Value? storage system that you must use to store any information you need to fulfill specific requests from users. The key designation is a free form text field that you will use as a descriptor. The value is required to be an array since most storage actions will contain more than one piece of data such as a username and password value set or OAuth tokens. The data will be securely sent to our servers where it will be encrypted and stored for later use.

$metricly->setRecord($key, $value) - Sets a basic key/value pair for the requesting company. $value must be an array or it will fail.

$metricly->getRecord($key) - returns the array you set in the setRecord call.

$metricly->deleteRecord($key=STRING) - Clears out a record for the company with the passed key.

The Metricly Response Class

We package a set of tools to easily handle return data back to Metricly after a request. After you instantiate the class there are several methods available.

Instantiate the class as you would any normal class.

$response = NEW MetriclyResponse();

$response->set_data($data=ARRAY) - Accepts an array for the main data container that Metricly is expecting for most calls.

$response->set_error($error_code=INT, $error_message=STRING) - If your plug-in encounters an error and cannot fulfill the request normally you can send back an error instead of a completed request. This lets Metricly know something has gone wrong so it can handle it accordingly. Error codes currently are arbitrary numeric values that will be implemented in the future. Error messages are descriptive messages that will be logged for further analysis. Please use a descriptive error message.

$response->commit() - finishes the session and packages up everything into JSON and sends it back to Metricly and exits the script.

Sample Plug-in