AMP Integration

Viafoura's Conversations, Live blogging, and Live Chat tools are 100% AMP compliant. The following documentation will guide you through a step-by-step integration process to get your AMP pages up and running.

AMP Conversations Integration

Step 1: Host an HTTPS Page that Serves the Widget

To integrate Viafoura conversations, you must host a non AMP https page that serves only the commenting widget. The page must be on a different domain than the one that you will serve your AMP pages on. You will need to have this domain allowlisted with Viafoura to enable commenting, please contact us and ask for the domain to be allowlisted, along with the domain alias you wish to use for your AMP pages.

📘

Note

We recommend that you host this page on your regular domain and host your AMP pages on https://amp.[domain].com

Example AMP Viafoura commenting page:
https://amp.[domain].com/viafoura-amp-commenting.html

<!doctype html>
<html lang="en">
    <head>
        <title>Viafoura AMP Comments Demo</title>
    </head>
    <body>
        /* The `amp-widget` attribute is required */
        <div class="viafoura">
            <vf-conversations amp-widget></vf-conversations>
        </div>
     
        <div class="viafoura">
            <vf-tray class="vf-amp-tray vf-tray--modal-override"></vf-tray>
        </div>
        <script>
           // calculate the data path based on the window query string
            var queryString = window.location.search.substring(1);
            const getQueryStringParam = function(key) {
                return decodeURIComponent((queryString.match(new RegExp(key + '=([^&]*)'))|| [])[1] || '');
            }
            const path = getQueryStringParam('path');
            const uniqueId = getQueryStringParam('uniqueId');
            const title = getQueryStringParam('title');

            // Set the path, unique id, and title meta tags on the head
            var head = document.head;

            if (path) {
                var urlMetaTag = document.createElement('meta');
                urlMetaTag.setAttribute('property', 'og:url');
                urlMetaTag.setAttribute('content', window.location.origin + path);
                head.appendChild(urlMetaTag);
            }

            if (uniqueId) {
                var uniqueIdMetaTag = document.createElement('meta');
                uniqueIdMetaTag.setAttribute('property', 'vf:unique_id');
                uniqueIdMetaTag.setAttribute('content', uniqueId);
                head.appendChild(uniqueIdMetaTag);
            }
            
            if (title) {
                  var titleTag = document.querySelector('title');
                  titleTag.textContent = title;
            }


            // inject vf js so we can guarantee the meta tags are set before viafoura runs
            var vfjs = document.createElement('script');
            vfjs.setAttribute('type', 'text/javascript');
            vfjs.setAttribute('async', true);
            vfjs.setAttribute('src', '//cdn.viafoura.net/vf-v2.js');
            document.getElementsByTagName('script')[0].insertBefore(vfjs, null);
            // Listen for commenting resize events and then bubble that event up that event to the amp-iframe to resize it
            // And throttle the resize since comments rerender and resize themselves frequently
            window.vfQ = window.vfQ || [];
            vfQ.push(function() {
                var locked = false;
                vf.$subscribe('commenting', 'resized', function() {
                    if (!locked) {
                        locked = true;
                        setTimeout(function() {
                            locked = false;
                            // Add a bit of buffer to the height for things like the "show more" button
                                                        // V2 widgets
                            const height = document.querySelector('.vf-commenting').clientHeight + 100;
                                                        // V3 widgets
                                                        const height = document.querySelector('.vf3-comments').clientHeight + 100;
                            window.parent.postMessage({
                                sentinel: 'amp',
                                type: 'embed-size',
                                height: height,
                            }, '*');
                        }, 50);
                    }
                });
            });
        </script>
    </body>
</html>

This will load the Viafoura amp-comments widget which will render the commenting widget and the tray widget.

🚧

The page that serves the widget must include the user authentication workflow

In order for users to be able to engage with Viafoura's widget, they will be required to be authenticated. Therefore the HTML page that is loading the widget must have all the necessary items to allow users to login or signup. Make sure to review the authentication integration details and enable authentication in your page.

🚧

The page that serves the widget must include the corresponding article page metatags

To ensure consistency across page analytics, moderation settings, and tools that retrieve and display page details (like the Trending Articles widget), the https page that serves the conversations widget for the AMP page must also include the Viafoura required metatags, displaying the same value of the corresponding article page.

Step 2: Import the AMP-iFrame Script

On your AMP pages, import the amp-iframe script:

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

Step 3: Point the AMP-iFrame to the Widget HTTPS Page

Place the amp-iframe on the page pointing to the AMP conversation page above. The Viafoura AMP conversation widget will parse the query string of the url to load the comments from that page. Replace the path with a unique identifier or the path representing the page you would like to display the thread for.

In the example below, the path is "/article.html" (%2F is a url encoded "/") and it will load the comments for the /article.html page. Please refer to our unique id documentation for more information.

This means that each AMP page with comments should point to the one Viafoura AMP conversation widget above, but should have a different path so that the comments for the specified page will be loaded.

Example AMP-iFrame:

<amp-iframe
           width=600
           height=400
           layout="responsive"
           sandbox="allow-scripts allow-same-origin allow-modals allow-popups allow-forms"
           resizable
           src="https://amp.[domain].com/viafoura-amp-commenting.html?container=commentingpage&isAmpPage=true"
>
           <!-- Point the iframe to the non-AMP commenting page -->
           <div overflow placeholder></div>
           <!-- AMP requires a placeholder to prevent content from suddenly jumping when it loads. This can be replaced with a placeholder of your choice -->
</amp-iframe>

AMP Live Blog Integration

Step 1: Host an HTTPS Page that Serves the Widget

In order to integrate Viafoura Live Blogging, you must host a non AMP https page that serves only the live blogging widget. The page must be on a different domain than the one that you will serve your AMP pages on. You will need to have this domain allowlisted with Viafoura to enable Liveblog, please contact us and ask for the domain to be allowlisted, along with the domain alias you wish to use for your AMP pages.

📘

Note

We recommend that you host this page on your regular domain and host your AMP pages on https://amp.[domain].com

Example AMP Viafoura live blogging page:
https://amp.[domain].com/viafoura-amp-blogging-widget.html

<!doctype html>
<html lang="en">
    <head>
        <link rel="stylesheet" type="text/css" href="base.css" />
        <script async='async' src='https://www.googletagservices.com/tag/js/gpt.js'></script>
        <script>
            var gptadslots = [];
            var googletag = googletag || {
                cmd: []
            };
            googletag.cmd.push(function() {
                googletag.pubads().enableSingleRequest();
                googletag.pubads().disableInitialLoad();
                googletag.enableServices();
            });
        </script>
    </head>
    <body>
        <div class="viafoura">
            <vf-livestory amp-widget></vf-livestory>
        </div>
        <div class="viafoura">
            <vf-tray class="vf-amp-tray"></vf-tray>
        </div>
        <script>
            var queryString = window.location.search.substring(1);
            const getQueryStringParam = function(key) {
                return decodeURIComponent((queryString.match(new RegExp(key + '=([^&]*)'))|| [])[1] || '');
            }
            const setMetaTag = function(property, content) {
                const metaTag = document.createElement('meta');
                metaTag.setAttribute('property', property);
                metaTag.setAttribute('content', content);
                head.appendChild(metaTag);
            }

            /**
             * Dynamically generates an ad and inserts it into the template when the Viafoura
             * Commenting Widget requests an ad.
             * Adapted from: https://support.google.com/dfp_premium/answer/4578089?hl=en#infiniteContents
             * @param  {String} slotName - id of the element to render the ad in
             */
            function generateAd(slotName) {
                // Generate next slot name
                var adUnitString = '/1234/travel/asia'; // This string should be replaced by your
                                                        // network code and ad unit you are targeting
                var size = [320, 50]; // the comment ad positions can accommodate any ad size,
                                    // but we recommend not using very tall ads and using ad size
                                    // mapping for different device sizes. See ad size mapping below
                // Define the slot itself, call display() to
                // register the div and refresh() to fetch the ad.
                googletag.cmd.push(function() {
                    // Define ad sizes based on viewport size
                    // NOTE ads are not responsive but new ads will be rendered to the appropriate size
                    // Adapted from https://support.google.com/dfp_premium/answer/4578089?hl=en#responsiveDesign
                    var mapping = googletag.sizeMapping()
                    .addSize([100, 100], [88, 31]) // Small ad
                    .addSize([320, 400], [[320, 50], [300, 50]]) // Accepts both common mobile banner formats
                    .addSize([320, 700], [300, 250]) // Same width as mapping above, more available height
                    .addSize([750, 200], [300, 250]) // Landscape tablet
                    .build();
                    // Create a new ad slot, pointing to the slotName given to this function
                    var slot = googletag.defineSlot(adUnitString, size, slotName)
                        .defineSizeMapping(mapping)
                        .addService(googletag.pubads());
                        // Add any targeting or any other modifications to the ad here
                    // Display the new ad
                    googletag.display(slotName);
                    googletag.pubads().refresh([slot]);
                });
            };
            
            const title = getQueryStringParam('title');
            const container = getQueryStringParam('container');

            // Set the title and container id meta tags on the head
            var head = document.head;

            if (title) {
                setMetaTag('vf:title', title);
            }
            if (container) {
                setMetaTag('vf:container_id', container);
            }
            
            // inject vf js so we can guarantee the meta tags are set before viafoura runs
            var vfjs = document.createElement('script');
            vfjs.setAttribute('type', 'text/javascript');
            vfjs.setAttribute('async', true);
            vfjs.setAttribute('src', '//cdn.viafoura.net/vf-v2.js');

            document.getElementsByTagName('script')[0].insertBefore(vfjs, null);

            window.vfQ = window.vfQ || [];

            window.vfQ.push(function() {
                var locked = false;
                vf.$subscribe('liveblog', 'resized', function() {
                    if (!locked) {
                        locked = true;
                        setTimeout(function() {
                            locked = false;
                            // Add a bit of buffer to the height for things like the "show more" button
                            const height = document.querySelector('.vf3-comments').clientHeight + 100;
                            window.parent.postMessage({
                                sentinel: 'amp',
                                type: 'embed-size',
                                height: height,
                            }, '*');
                        }, 50);
                    }
                });
              
                // Show ads in the liveblog
                vf.$subscribe('vf-ads', 'requestCommentAd', generateAd);
            });
        </script>
    </body>
</html>

This will load the Viafoura live-stories widget which will render the live blogging widget and the tray widget.

Step 2: Import the AMP-iFrame Script

On your AMP pages, import the amp-iframe script:

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

Step 3: Point the AMP-iFrame to the Widget HTTPS Page

Place the amp-iframe on the page pointing to the AMP live blogging page above. The Viafoura AMP live blogging widget will parse the query string of the url to determine which page's blog you want to load. Replace the container with a unique identifier to indicate which blogging widget you would like to load. To learn more about containers, see our container id documentation.

This means that each AMP page with the blog should point to the one Viafoura AMP blogging widget above, but should have a different container so that the blog for the specified container will be loaded

Example AMP-Iframe with container:

// V3 widgets
<amp-iframe
           width=600
           height=400
           layout="responsive"
           sandbox="allow-scripts allow-same-origin allow-modals allow-popups allow-forms"
           resizable
           src="https://amp.[domain].com/viafoura-amp-commenting.html?container=livebloggingpage&isAmpPage=true"
>
           <!-- Point the iframe to the non-AMP commenting page -->
           <div overflow placeholder></div>
           <!-- AMP requires a placeholder to prevent content from suddenly jumping when it loads. This can be replaced with a placeholder of your choice -->
</amp-iframe>

AMP Community Chat Integration

Step 1: Host an HTTPS Page that Serves the Widget

In order to integrate Viafoura Community Chat, you must host a non AMP https page that serves only the community chat widget. The page must be on a different domain than the one that you will serve your AMP pages on. You will need to have this domain allowlisted with Viafoura to enable chat, please contact us and ask for the domain to be allowlisted, along with the domain alias you wish to use for your AMP pages.

📘

Note

We recommend that you host this page on your regular domain and host your AMP pages on https://amp.[domain].com

Example AMP Viafoura community chat page:
https://amp.[domain].com/viafoura-amp-chat-widget.html

<!doctype html>
<html lang="en">
    <head></head>
    <body>
        <div class="viafoura" style="height: 550px;">
            <vf-livechat></vf-livechat>
        </div>
        <div class="viafoura">
            <vf-tray class="vf-amp-tray vf-tray--modal-override"></vf-tray>
        </div>
        <script>
            var queryString = window.location.search.substring(1);
            const getQueryStringParam = function(key) {
                return decodeURIComponent((queryString.match(new RegExp(key + '=([^&]*)'))|| [])[1] || '');
            }
            const setMetaTag = function(property, content) {
                const metaTag = document.createElement('meta');
                metaTag.setAttribute('property', property);
                metaTag.setAttribute('content', content);
                head.appendChild(metaTag);
            }

            const title = getQueryStringParam('title');
            const container = getQueryStringParam('container');

            // Set the title and container id meta tags on the head
            var head = document.head;

            if (title) {
                setMetaTag('vf:title', title);
            }
            if (container) {
                setMetaTag('vf:container_id', container);
            }

            // inject vf js so we can guarantee the meta tags are set before viafoura runs
            var vfjs = document.createElement('script');
            vfjs.setAttribute('type', 'text/javascript');
            vfjs.setAttribute('async', true);
            vfjs.setAttribute('src', 'options.js');
            document.getElementsByTagName('script')[0].insertBefore(vfjs, null);
            // Listen for commenting resize events and then bubble that event up that event to the amp-iframe to resize it
            // And throttle the resize since comments rerender and resize themselves frequently
            window.vfQ = window.vfQ || [];
            var locked = false;
        </script>
    </body>
</html>

This will load the Viafoura livechat widget which will render the community chat widget and the tray widget.

Step 2: Import the AMP-iFrame Script

On your AMP pages, import the amp-iframe script:

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

Step 3: Point the AMP-iFrame to the Widget HTTPS Page

Place the amp-iframe on the page pointing to the AMP community chat page above. The Viafoura AMP community chat widget will parse the query string of the url to determine which page's blog you want to load. Replace the container with a unique identifier to indicate which community chat widget you would like to load. To learn more about containers, see our container id documentation.

This means that each AMP page with the chat should point to the one Viafoura AMP community chat widget above, but should have a different container so that the blog for the specified container will be loaded

Example AMP-Iframe with container:

<amp-iframe
           width=600
           height=400
           layout="responsive"
           sandbox="allow-scripts allow-same-origin allow-modals allow-popups allow-forms"
           resizable
           src="https://amp.[domain].com/viafoura-amp-chat-widget.html?container=amp_article_page&isAmpPage=true"
>
           <!-- Point the iframe to the non-AMP chat page -->
           <div overflow placeholder></div>
           <!-- AMP requires a placeholder to prevent content from suddenly jumping when it loads. This can be replaced with a placeholder of your choice -->
 </amp-iframe>

Analytics for AMP Viafoura Conversations pages

Analytics data, such as page views or attention time, will be tracked for the linked page rather than the canonical page url. I.e. they will be tracked for the page you pass in inside the querystring rather than the page that is serving the commenting widget (amp-widget.html).

📘

Note

If you want to segment your Viafoura analytics by Amp vs non-Amp pages, you will need to pass an additional querystring parameter into the amp-widget.html page so that it can identify an amp page. To indicate that the widget is being loaded for an amp page, pass “isAmpPage=true” as a querystring parameter. All pages without this parameter passed in will be treated as a non-Amp page.


Did this page help you?