NAV Navbar
  • Website tracking
  • Website video tracking
  • Application tracking
  • AMP tracking
  • Instant Articles tracking
  • CTR & Headline Testing
  • Other
  • Website tracking

    The document contains guides on setting up tracking for Example project.

    If you would like to migrate from the previous version, please contact your manager beforehand.

    1. Mark up article containers

    To track scroll depth of articles, surround them with a block that has the data-io-article-url attribute which value matches with URL from browser's location bar (same as a value of window.location.href).

    <div data-io-article-url="https://example.onthe.io/article-url-actual">
       <!-- body of an article goes here  -->
    </div>
    

    2. Add tracking code

    To load tracker, add a version of the following code as close to the opening <head> tag on following pages:

    1. Home page
    2. Category pages
    3. Article pages
    4. All other pages of mobile website
    5. All other pages of desktop website

    Example for an article page. You need to replace values of the configuration object with information about your page

    <script async src="https://cdn.onthe.io/io.js/{id}"></script>
    <script>
    window._io_config = window._io_config || {};
    window._io_config["0.2.0"] = window._io_config["0.2.0"] || [];
    window._io_config["0.2.0"].push({
        page_url: "https://example.com/article-url-actual?utm_source=example",
        page_url_canonical: "https://example.com/article-url-canonical",
        page_title: "My page title",
        page_type: "article",
        page_language: "en",
        article_authors: ["John Appleseed", "Marie Curie"],
        article_categories: ["Category 1", "Category 2"],
        article_type: "longread",
        article_word_count: "101",
        article_publication_date: "Fri, 09 Feb 2018 12:39:12 GMT"
    });
    </script>
    

    Example for a non-article page

    <script async src="https://cdn.onthe.io/io.js/{id}"></script>
    <script>
    window._io_config = window._io_config || {};
    window._io_config["0.2.0"] = window._io_config["0.2.0"] || [];
    window._io_config["0.2.0"].push({
        page_url: "https://example.com/non-article-url-actual?utm_source=example",
        page_url_canonical: "https://example.com/non-article-url-canonical",
        page_title: "My page title",
        page_type: "default",
        page_language: "en"
    });
    </script>
    

    Example for the home page

    <script async src="https://cdn.onthe.io/io.js/{id}"></script>
    <script>
    window._io_config = window._io_config || {};
    window._io_config["0.2.0"] = window._io_config["0.2.0"] || [];
    window._io_config["0.2.0"].push({
        page_url: "https://example.com/",
        page_url_canonical: "https://example.com/",
        page_title: "My page title",
        page_type: "main",
        page_language: "en"
    });
    </script>
    

    Configuration fields

    For values to be compatible with JavaScript object syntax, you need to replace " with &quot;, and remove line break characters from them.

    Name Type Description
    page_url String URL that is displayed in a browser window. Including URL parameters.
    page_url_canonical String Canonical URL of a page. Without utm_source or any other query parameters. Used to combine pages that may be available through multiple URLs into one entity.
    page_title String Title that you prefer to see in a dashboard.
    page_type String Use main value for the home page, an initial page of a website. Use article for pages with articles. Use default for all other pages.
    page_language String Two latter language code of a page according to ISO 639-1 (e.g. en, ru).
    article_authors Array List of authors for a specific article.
    article_categories Array List of categories for a specific article.
    article_type String Type of a specific article. Used to filter articles. Can hold arbitrary values.
    article_word_count String Number of words in a specific article.
    article_publication_date String Publication date of an article according to RFC-822 Date and Time Specification with the exception that the year should be expressed as four digits.

    Publication date examples

    Variant Description
    Fri, 23 Feb 2018 13:00:00 GMT In UTC
    Fri, 23 Feb 2018 08:00:00 EST With a local timezone
    Fri, 23 Feb 2018 15:00:00 +0200 With a local offset to UTC

    Website video tracking

    Example of a video tag with an attribute to specify title

    <video data-io-video-title="My video title" src="/video-1"></video>
    

    To indicate which HTML5 videos you want to track, add data-io-video-title attribute on video tags. Value of the attribute would be used as title for currently playing video.

    Videos embedded using YouTube and Vimeo will be tracked automatically.

    Application tracking

    Sending data is as simple as sending simple HTTPS GET requests.

    Example of sending pageviews metric

    https://tt.onthe.io/?k[]={app_id}:pageviews[page:My%20Article%20Title,category:SPORT]&s=a63fa7bd0cb420398c55518ee76b0a3f
    
    # https://tt.onthe.io/
    #     ?k[]={app_id}:
    #         pageviews[
    #             url:/example/article,
    #             pr:/example/article_previous,
    #             page:Breaking%20news%3A%20Project%20General%20has%20been%20connected%20to%20io%20analytics%20system,
    #             category:Sport,
    #             type_article:Longread,
    #             author:John%20Doe,
    #             platform:iOS,
    #             referrer:app,
    #             domain:example.com,
    #             ]
    #     &s=a63fa7bd0cb420398c55518ee76b0a3f
    

    String pageviews is an example of a metric, strings page and category are slices.

    All values in slices should be URL-encoded and be in UTF-8 encoding.

    Metrics Description

    Name Event
    pageviews User opens an article
    read_finished User read an article to the end
    uniques User opens an app for the first time during last 24 hours
    visits User session has been ended more than 15 minutes ago
    time It is been 10 second after user opened an article or previous time metric was sent

    Slices Description

    Name Status Description
    url required pathname of a page's URL
    pr required pathname of a previous page's URL
    page required Title of a page
    category optional Category of an article
    type_article optional Type of an article
    author required* Author of a article. * only for articles
    platform required Platform of an app
    referrer required Referrer domain without TLD
    domain required hostname of a page's URL

    AMP tracking

    If you want to track data from Google AMP pages, you need to insert additional HTML code into your website.

    1. Add canonical URL

    Make sure link rel="canonical" tag is added into <head> tag and contains different values in href on every page.

    Example

    <link rel="canonical" href="https://example.onthe.io/article-url-canonical">
    

    2. Enable AMP analytics

    Include analytics framework by adding <script> tag into <head> tag of your website pages.

    <script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
    

    3. Add tracking code

    Add tracking code into <body> tag of on an every article page.

    If you want to track some specific data instead of the default one, you can customize values inside vars block using server-side scripts.

    Example of a variables block

    "vars": {
        "page_title": "${title}",
        "page_type": "article",
        "page_language": "en",
        "article_authors": "John Appleseed|Marie Curie",
        "article_categories": "Category 1|Category 2",
        "article_type": "longread",
        "article_word_count": "101",
        "article_publication_date": "Fri, 09 Feb 2018 12:39:12 GMT"
    },
    

    Default tracking code

    <amp-analytics>
        <script type="application/json">
            {
                "requests": {
                    "pageview": "https://tt.onthe.io/?k[]={app_id}:pageviews[user_id:${clientId(_io_un)},author:${article_authors},referrer_uri:${documentReferrer},url:${canonicalPath},domain:${canonicalHostname},user_agent:${userAgent},page:${page_title},platform:amp,language:${page_language},category:${article_categories},type_article:${article_type},word_count:${article_word_count},pub_date:${article_publication_date},page_type:${page_type}]",
                    "read_top": "https://tt.onthe.io/?k[]={app_id}:read_top[user_id:${clientId(_io_un)},author:${article_authors},referrer_uri:${documentReferrer},url:${canonicalPath},domain:${canonicalHostname},user_agent:${userAgent},page:${page_title},platform:amp,language:${page_language},category:${article_categories},type_article:${article_type},word_count:${article_word_count},pub_date:${article_publication_date},page_type:${page_type}]",
                    "read_middle": "https://tt.onthe.io/?k[]={app_id}:read_middle[user_id:${clientId(_io_un)},author:${article_authors},referrer_uri:${documentReferrer},url:${canonicalPath},domain:${canonicalHostname},user_agent:${userAgent},page:${page_title},platform:amp,language:${page_language},category:${article_categories},type_article:${article_type},word_count:${article_word_count},pub_date:${article_publication_date},page_type:${page_type}]",
                    "read_bottom": "https://tt.onthe.io/?k[]={app_id}:read_bottom[user_id:${clientId(_io_un)},author:${article_authors},referrer_uri:${documentReferrer},url:${canonicalPath},domain:${canonicalHostname},user_agent:${userAgent},page:${page_title},platform:amp,language:${page_language},category:${article_categories},type_article:${article_type},word_count:${article_word_count},pub_date:${article_publication_date},page_type:${page_type}]",
                    "read_finished": "https://tt.onthe.io/?k[]={app_id}:read_finished[user_id:${clientId(_io_un)},author:${article_authors},referrer_uri:${documentReferrer},url:${canonicalPath},domain:${canonicalHostname},user_agent:${userAgent},page:${page_title},platform:amp,language:${page_language},category:${article_categories},type_article:${article_type},word_count:${article_word_count},pub_date:${article_publication_date},page_type:${page_type}]",
                    "time": "https://tt.onthe.io/?k[]={app_id}:time[platform:amp,url:${canonicalPath}]"
                },
                "vars": {
                    "page_title": "${title}",
                    "page_type": "article",
                    "page_language": "",
                    "article_authors": "",
                    "article_categories": "",
                    "article_type": "",
                    "article_word_count": "",
                    "article_publication_date": ""
                },
                "triggers": {
                    "trackPageview": {
                        "on": "visible",
                        "request": "pageview"
                    },
                    "trackReadTop" : {
                        "on" : "scroll",
                        "scrollSpec": {
                            "verticalBoundaries": [25]
                        },
                        "request": "read_top"
                    },
                    "trackReadMiddle" : {
                        "on" : "scroll",
                        "scrollSpec": {
                            "verticalBoundaries": [50]
                        },
                        "request": "read_middle"
                    },
                    "trackReadBottom" : {
                        "on" : "scroll",
                        "scrollSpec": {
                            "verticalBoundaries": [75]
                        },
                        "request": "read_bottom"
                    },
                    "trackReadFinished" : {
                        "on" : "scroll",
                        "scrollSpec": {
                            "verticalBoundaries": [90]
                        },
                        "request": "read_finished"
                    },
                    "pageTimer": {
                        "on": "timer",
                        "timerSpec": {
                            "interval": 10
                        },
                        "request": "time"
                    }
                },
                "transport": {
                    "beacon": false,
                    "xhrpost": false,
                    "image": true
                }
            }
        </script>
    </amp-analytics>
    

    Variables description

    Use | symbol as a separator for multiple values in article_author and article_categories.

    Name Description
    page_title Title that you prefer to see in a dashboard.
    page_type Use article for pages with articles. Use default for all other pages.
    page_language Two latter language code of a page according to ISO 639-1 (e.g., en, ru).
    article_authors List of authors for a specific article.
    article_categories List of categories for a specific article.
    article_type Type of a specific article. Used to filter articles.
    article_word_count Number of words in a specific article.
    article_publication_date Publication date of an article according to RFC-822 Date and Time Specification with the exception that the year should be expressed as four digits.

    Publication date examples

    Variant Description
    Fri, 23 Feb 2018 13:00:00 GMT In UTC
    Fri, 23 Feb 2018 08:00:00 EST With a local timezone
    Fri, 23 Feb 2018 15:00:00 +0200 With a local offset to UTC

    Instant Articles tracking

    To track data from Instant Articles pages add HTML block into pages you provide to Facebook using RSS feed.

    <figure class="op-tracker">
        <iframe>
            <script async src="https://cdn.onthe.io/io.js/{id}"></script>
        </iframe>
    </figure>
    

    CTR & Headline Testing

    To track CTR and use Headline Testing on your website you would need to mark up sections, blocks, and headlines.

    Example

    <div data-vr-zone="Header section">
        <!-- Default example -->
        <div data-vr-contentbox="With a hero image" data-vr-contentbox-url="http://www.example.com/page1.html">
            <h2 data-vr-headline>Article Title</h2>
            <a href="http://www.example.com/page1.html">Link</a>
        </div>
        <!-- With a nested headline -->
        <div data-vr-contentbox="Second position" data-vr-contentbox-url="/page2.html">
            <a href="/page2.html">
                <h2 data-vr-headline>Article Title</h2>
            </a>
        </div>
        <!-- With everything nested in an anchor -->
        <a data-vr-contentbox="Position 3" data-vr-contentbox-url="/page3.html">
            <h2 data-vr-headline>Article Title</h2>
        </a>
    </div>
    
    Attribute name Description
    data-vr-zone Marks a block that contains blocks with articles
    data-vr-contentbox Marks a block with title/link/description of an article. Specifies a unique position of a block.
    data-vr-contentbox-url Specifies the canonical URL of an article inside a block marked with data-vr-contentbox.
    data-vr-headline Marks the headline inside data-vr-contentbox.

    Other

    Track authors using IDs

    To track authors of articles using IDs instead of names, please contact your .io manager and provide them a link to a document that will be used for name matching. JSON document should follow the structure from the example, hosted on your end and be openly accessible.

    Example of https://example.onthe.io/authors.json

    [
        {
            "1": "John Doe"
        },
        {
            "2": "Peter Parker"
        }
    ]
    

    Turbo Pages tracking

    Your tracking code

    <turbo:analytics
        type="custom"
        url="https://tt.onthe.io/?k[]={app_id}:pageviews[platform:yandex_turbo,href:{originalURL},page:{pageTitle},referrer_uri:{referrer},user_id:{clientId}]&#x26;{random}" >
    </turbo:analytics>
    

    To enable tracking, you would need to add the following code inside <channel> tag of RSS feeds you use for Turbo Pages.

    Example of an RSS feed

    <rss
        xmlns:yandex="http://news.yandex.ru"
        xmlns:media="http://search.yahoo.com/mrss/"
        xmlns:turbo="http://turbo.yandex.ru"
        version="2.0"
        >
        <channel>
            <turbo:analytics
                type="custom"
                url="https://tt.onthe.io/?k[]={app_id}:pageviews[platform:yandex_turbo,href:{originalURL},page:{pageTitle},referrer_uri:{referrer},user_id:{clientId}]&#x26;{random}" >
            </turbo:analytics>
            <item turbo="true">
                <link>http://www.example.com/page1.html</link>
                <turbo:content>
                    ...
                </turbo:content>
            </item>
        </channel>
    </rss>
    

    API

    You could get data from API by sending POST-requests.

    Your endpoint: https://api.onthe.io/.

    Your secret key: {log-in to see your secret key}.

    Request body example: TOP-20 articles for today

    {
        "key" : "{log-in to see your secret key}",
        "entities" : {
            "articles" : {
                "entity" : "articles",
                "details" : ["pageviews", "author", "category", "timeread", "social", "sources"]
            }
        },
        "options" : {
            "period" : {
                "name" : "today"
            },
            "per_page" : 20
        }
    }
    

    Request body example: Categories data for a week

    {
        "key" : "{log-in to see your secret key}",
        "entities" : {
            "categories" : {
                "entity" : "categories",
                "details" : ["title", "pageviews"]
            }
        },
        "options" : {
            "period" : {
                "name" : "week"
            }
        }
    }
    

    Request body example: TOP-10 authors for today

    {
        "key" : "{log-in to see your secret key}",
        "entities" : {
            "authors" : {
                "entity" : "authors",
                "details" : ["pageviews", "readability", "count_pub"]
            }
        },
        "options" : {
            "period" : {
                "name" : "today"
            },
            "per_page" : 10
        }
    }
    

    Request body example: List of articles filtered by author

    {
        "key" : "{log-in to see your secret key}",
        "entities" : {
            "articles" : {
                "entity" : "articles",
                "details" : ["pageviews", "author", "category", "timeread", "social", "sources"],
                "filters" : {
                    "author" : "author_id-value-from-authors-entity"
                }
            }
        },
        "options" : {
            "period" : {
                "name" : "today"
            },
            "per_page" : 20
        }
    }
    

    Request body example: List of articles filtered by category

    {
        "key" : "{log-in to see your secret key}",
        "entities" : {
            "articles" : {
                "entity" : "articles",
                "details" : ["pageviews", "author", "category", "timeread", "social", "sources"],
                "filters" : {
                    "category" : "category_id-value-from-categories-entity"
                }
            }
        },
        "options" : {
            "period" : {
                "name" : "today"
            },
            "per_page" : 20
        }
    }
    

    Period option examples (one per line)

    {"period": {"name": "realtime"}}
    {"period": {"name": "now"}}
    {"period": {"name": "hour"}}
    {"period": {"name": "today"}}
    {"period": {"name": "week"}}
    {"period": {"name": "month"}}
    {"period": {"name": "range", "at_from": "2017-05-20", "at_to": "2017-05-25"}}
    {"period": {"name": "today", "at": "2017-07-01"}}
    

    Example in JavaScript: TOP-10 authors for today

    var io={ajax:function(e,n,t,r){var o=new XMLHttpRequest;o.open(r||"POST",e,!0),o.onreadystatechange=function(){4==o.readyState&&200!=o.status&&t&&t(null),4==o.readyState&&200==o.status&&t&&t(o.responseText?JSON.parse(o.responseText):null)},o.setRequestHeader("Content-type","application/x-www-form-urlencoded"),o.send(n?io.query(n):null)},urlencode:function(e){return e=(e+"").toString(),encodeURIComponent(e).replace(/!/g,"%21").replace(/'/g,"%27").replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/\*/g,"%2A").replace(/%20/g,"+")},query:function(e,n,t){var r,o,u=[],a=this,c=function(e,n,t){var r,o=[];if(!0===n?n="1":!1===n&&(n="0"),null!==n&&"object"==typeof n){for(r in n)null!==n[r]&&o.push(c(e+"["+r+"]",n[r],t));return o.join(t)}return"function"!=typeof n?a.urlencode(e)+"="+a.urlencode(n):"function"==typeof n?"":void 0};t||(t="&");for(o in e)r=e[o],n&&!isNaN(o)&&(o=String(n)+o),u.push(c(o,r,t));return u.join(t)}};
    
    var params = {
        "key" : "{log-in to see your secret key}",
        "entities" : {
            "authors" : {
                "entity" : "authors",
                "details" : ["pageviews", "readability", "count_pub"]
            }
        },
        "options" : {
            "period" : {
                "name" : "today"
            },
            "per_page" : 10
        }
    };
    
    io.ajax("https://api.onthe.io/", params, function (r) {
        console.log(r); 
    });
    

    Example in PHP: TOP-10 authors for today

    <?php
    
    $params = [
        'key' => '{log-in to see your secret key}',
        'entities' => [
            'authors' => [
                'entity' => 'authors',
                'details' => ['pageviews', 'readability', 'count_pub']
            ]
        ],
        'options' => [
            'period' => [
                'name' => 'today'
            ],
            'per_page' => 10
        ]
    ];
    
    
    $url = 'https://api.onthe.io/';
    
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    $response = curl_exec($ch);
    curl_close($ch);
    
    print_r(json_decode($response, true));
    
    Key Type Description
    key String Your secret key
    entities Object An array of parameters you want to get could contain multiple number of entities to select
    options Object An array of parameters, which will be added for each entity-element from entities array can consist of such elements
    Option Type Description
    period Object A time frame to extract the data
    per_page Number Number of elements on one page
    offset Number Page number (starts from 0)
    order String Sort order (e.g., pageviews, fb, readability, recirculation)
    direction String Sequence (ASC or DESC)