UGC Techdocs
  • Introduction
  • Guides
    • Analytics
      • Tracking UGC on Adobe Analytics
      • Tracking Widget interactions with Google Analytics
    • Direct Uploader
      • How to add Custom Data to Direct Uploader
      • How to capture Custom Data on Direct Uploader
      • How to automatically tag data on Direct Uploader
      • How to Customize error messages on Direct Uploader
      • How to Track Direct Uploader form submissions with Google Analytics (Universal & GA 4)
    • Data Templates
      • Creating a Data Template
    • Rights via Registration
      • Capture Custom Data on Rights by Registration Form
      • Styling Rights via Registration Form
    • REST API
      • Caching REST API results for optimization
      • Posting content into Nosto via Tile API
      • Posting images into Nosto via Tile API
    • Onsite Widgets (2.0)
      • Blank Canvas
        • How to Use the Blank Canvas to Create a Twitter Count Widget
        • Creating an Auto-Scrolling Carousel using Blank Canvas
        • Creating Gallery Widget by Using the Blank Canvas Widget
        • Creating a simple Hover effect using Blank Canvas
        • Creating a Word Cloud using Blank Canvas
        • Creating Your Widget by Using the Blank Canvas
      • Bind your own Events
      • Creating a Grid Widget from Waterfall
      • Create a Q&A Widget using Data Templates
      • Displaying a Widget in a Mobile App
      • Dynamically Specify Products to Display in Widget
      • Dynamically specify what Tile to display in a Widget
      • How to add a title / subtitle to a widget
      • How to localize the load more button on widgets
      • How to overlay existing Google Map with the UGC Map Widget
      • Styling cross-sellers on Grid and Carousel Widgets
      • How to Load External JS and CSS into Widgets
      • Profiling Widget Performance
      • Re-targeting with Widgets and Facebook Pixel
      • Render Widget filters dynamically
      • Styling Carousel Widget
      • Styling Grid Widget
      • Styling Masonry Widget
      • Styling Waterfall Widget
      • Styling Widget Expanded Tile
      • Styling Widget Shopspots
      • Using Web Fonts in Widgets
    • Digital Screens
      • Customizing Carousel Event Screen
      • Customizing Mosaic Event Screen
      • Customizing Scrollwall Event Screen
      • Customizing the Mosaic Event Screen to Have 9 Even Tiles
    • Email
      • Adding Location to an Email Tile
      • Styling the Email Widget
    • Integrations
      • DoubleClick
        • UGC Ads with Nosto and Google DoubleClick
      • Zapier
        • Consuming UGC Webhooks via Zapier
      • Mailchimp
        • Bring Social Content into a Mailchimp Campaign
    • Webhooks
      • Trigger notifications when content is in the moderation queue
  • Widgets
  • API Docs
    • JavaScript API
      • Widgets
        • Introduction
        • API Reference for Content Widgets
        • API Reference for Blank Canvas
        • API Reference for Map Widget
      • Digital Screens
        • Introduction
        • API Reference
    • Content API
      • Reference
    • REST API
      • Reference
        • Filters API
        • Moderation Views API
        • Tags API
        • Terms API
        • Tiles API
        • Users API
        • Widgets API
        • Automation Rules API
        • REST API Reference Widgets style and config
      • Best Practices
    • Webhooks
  • Enterprise Tools
    • Automation Rules
      • Triggers
      • Actions
      • Samples
    • Data Templates
    • User Access Control (UAC)
    • Single Sign On (SSO)
    • Enterprise Admin User Interface (EAUI)
    • Zapier
  • Commerce Tools
    • Product Feeds
    • Widget Implementation
    • Reporting
    • Integrations
      • Google Tag Manager
      • Magento
      • SalesForce Commerce Cloud
      • Shopify
      • Shopify Add To Cart
        • Global Variant Mapping for Add to Cart
        • Customise Add to Cart Widget Experience
  • Analytics
    • Google Analytics 4
      • Getting Started
      • Widgets Events
      • E-commerce Events
      • Email Events
  • Terms of Use
Powered by GitBook
On this page
  • Introduction
  • The Common Approach
  • Blank Canvas approach
  • Steps
  • Conclusion
  • Widget code for reference
  • Javascript
  • CSS
  • Layout

Was this helpful?

  1. Guides
  2. Onsite Widgets (2.0)
  3. Blank Canvas

How to Use the Blank Canvas to Create a Twitter Count Widget

PreviousBlank CanvasNextCreating an Auto-Scrolling Carousel using Blank Canvas

Last updated 4 months ago

Was this helpful?

Introduction

Blank Canvas provides a fairly flexible way to display the information ingested in Visual UGC and allows us to create unique widgets. Sometimes the desired outcome is not to display the actual user generated content, but to use the ingested items count to unlock discounts (or any sort of information) when those numbers hit some sort of thresholds. This was the case of one of our clients: they wanted to create a progress bar and unlock five offers in a particular event.

The Common Approach

Usually this is achieved by creating a custom application that uses the API to retrieve a summary from within a certain term or filter. This has a set of cons:

  1. To host a custom app implies more work and higher costs.

  2. It may imply using a database.

  3. The developer uses only the API and doesn’t leverage the widgets editor.

Blank Canvas approach

Advantages:

  1. Faster development

  2. No hosting needed

Steps

  1. The first step may look like a workaround but it is valid still and reflects the flexibility of the platform. By default, Nosto's UGC provides the UGC data as the pieces of information to render. This is not what we need for this particular case, so we can ignore/remove this callback all together: Stackla.loadTilesByFilter(function (tiles) {…}); Instead, we will use our own API call:


$(document).ready(function() {
    $.get('https://12345678.execute-api.ap-southeast-2.amazonaws.com/staging', function( resp ) {
        ...
    });
});
  1. That particular endpoint refers to Nosto's UGC API: https://api.Stackla.com/api/filters/123456/summaries?aggregated_by=default&stack={your_stack}&access_token={your_access_token}

    It was proxied with AWS' API Gateway and cached with AWS' Cloud Front. This was done in order to prevent Nosto's UGC API to be hit more than 450 times during the 15 minutes time window. That method of proxing is reliable, easy to set up and cheap.

  2. The returned summary needs to be parsed/manipulated and then we can invoke the following method:


Stackla.render({...});

Where the parameter is a valid JSON element.

  1. The “layout” provided by the blank canvas framework will be rendered with the provided information. Please refer to https://mustache.github.io/ to understand about the templating language.

  2. The CSS can now be edited to style the widget and make it responsive and nice-looking.

  3. If there are some resources, we can use the media library provided by Stackla. By doing so, we avoid using a third party system to host the images, fonts or any file we may need.

Conclusion

The development process was quick and straightforward, even though this was the first time we used the Blank Canvas Widget in this way.


Stackla.GoConnect.setText(placeholderName, newPlaceholderValue)

Widget code for reference

Javascript


var threshold1 = 1000, threshold2 = 2000, threshold3 = 5000;
var initialDegrees = 0;
var animTime = 1000;
var totalStages = 4;

Number.prototype.format = function (n, x) {
    var re = '\d(?=(\d{' + (x || 3) + '})+' + (n > 0 ? '\.' : '$') + ')';
    return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '$&,');
};


$(document).ready(function () {
    $.get('https://abcdef123456.cloudfront.net', function (resp) {
        if (resp.errors.length === 0) {
            var nTweets = 0;
            if(typeof resp.data !== 'undefined' && typeof resp.data[0] !== 'undefined' && typeof resp.data[0].quantity !== 'undefined') {
                nTweets = resp.data[0].quantity;
            }

            //Mocked!
            //nTweets = 500;
            Stackla.render({
                extra: {
                    tweets: nTweets,
                    offer: [
                        {
                            num: 1,
                            enabled: nTweets >= threshold1,
                            threshold: threshold1.format(),
                            name: "Offer 1",
                            description: ["Promo 1","Description promo 1"],
                            clickthrough: "https://www.fake-host.com/offers/12345"
                        },
                        {
                            num: 2,
                            enabled: nTweets >= threshold2,
                            threshold: threshold2.format(),
                            name: "Offer 2",
                            description: ["Promo 2","Description promo 2"],
                            clickthrough: "https://www.fake-host.com/offers/23456"
                        },
                        {
                            num: 3,
                            enabled: nTweets >= threshold3,
                            threshold: threshold3.format(),
                            name: "Offer 3",
                            description: ["Promo 3","Description promo 3"],
                            clickthrough: "https://www.fake-host.com/offers/34567"
                        }
                    ]
                }
            });
            if (nTweets  0.33) {
            percComplete = 0.33 + 1 / (threshold2 - threshold1) * (tweets - threshold1) * 0.33;
            if (percComplete > 0.66) {
                percComplete = 0.66 + 1 / (threshold3 - threshold2) * (tweets - threshold2) * 0.66;
                if (percComplete > 1) {
                    percComplete = 1;
                }
            }
        }
        var timePerStage = parseInt(animTime / step);
        window.setTimeout(function () {
            animateRecursive(0, step, timePerStage);
        }, 0);
    }, 1000);
};

CSS


body {
    border: 0;
    overflow: hidden;
}
.container {
    overflow: hidden;
    h1 {
        margin-top: 2px;
    }
    .offers-cont {
        margin: 0 auto;
    }
    .clearfix {
        overflow: auto;
    }
    .offer {
        float: left;
        width: 362px;
        height: 275px;
        background-color: #343433;
        color: #666565;
        margin: 5px;
        padding: 10px;
        text-align: center;
        .enabled {
            position: relative;
            width: 100%;
            height: 100%;
        }
        h1 {
            margin-top: 15px;
            margin-bottom: 10px;
        }
        .btn-cont {
            position: absolute;
            bottom: 30px;
            padding: 10px;
            border: 1px solid #FFF;
        }
        .desc {
            margin-top: 12px;
        }
        &.enabled {
            background-color: #db0626;
            color: #FFF;
            a, a:active, a:hover {
                color: #FFF;
                text-decoration: none;
                font-size: 1.3em;
                padding: 0;
                margin: 0;
            }
        }
    }
    .offer-1,
    .offer-2,
    .offer-3 {
        position: absolute;
        text-align: center;
        .separator {
            margin-left: auto;
            margin-right: auto;
        }
    }
    .offers-cont {
        margin-top: 60px;
    }
    .separator {
        background-color: #db0626;
        height: 4px;
        width: 55px;
        margin: 15px 0;
    }
    .stages {
        overflow: hidden;
        max-width: 700px;
        width: 100%;
        margin: 0 auto;
        transition: background-image 1.5s ease;
        background: url('https://web-assets.stackla.com/someclient.stackla.comhttp://sdp-media.dev/images/customimages/2016-11/1479441831/stage1.png') top center;
        background-size: contain;
        &.stage-2 {
            background-image: url('https://web-assets.stackla.com/someclient.stackla.comhttp://sdp-media.dev/images/customimages/2016-11/1479441822/stage2.png');
        }
        &.stage-3 {
            background-image: url('https://web-assets.stackla.com/someclient.stackla.comhttp://sdp-media.dev/images/customimages/2016-11/1479441818/stage3.png');
        }
        &.stage-4 {
            background-image: url('https://web-assets.stackla.com/someclient.stackla.comhttp://sdp-media.dev/images/customimages/2016-11/1479441810/stage4.png');
        }
    }
}

Layout



<div class="track clearfix">
    <div class="container">
    {{#extra.offer}}
            <div class="offer-legend offer-{{num}}">
                <h1>{{name}}</h1>
                <div class="separator"></div>
                <div class="desc">{{threshold}} tweets to unlock</div>
            </div>
    {{/extra.offer}}
    <div class="stages">
            <div></div>
        </div>
        <div class="offers-cont clearfix">
    {{#extra.offer}}
    <div class="offer o{{num}} {{^enabled}}disabled{{/enabled}} {{#enabled}}enabled{{/enabled}}">
    {{^enabled}}
                    <div class="disabled">
                        <h1>{{name}}</h1>
                        <img src="https://s3-ap-southeast-2.amazonaws.com/client/assets/gray-lock.png" />
                        <div class="desc">Will be unlocked<br/>after {{threshold}} tweets</div>
                    </div>
    {{/enabled}}
    {{#enabled}}
                    <div class="enabled">
                        <h1>{{name}}</h1>
                        <div class="desc">
    {{#description}}
    {{.}}<br/>
    {{/description}}
    </div>
                        <div class="btn-cont">
                            <a href="{{clickthrough}}" target="_blank">Claim now</a>
                        </div>
                    </div>
    {{/enabled}}
    </div>
    {{/extra.offer}}
    </div>
    </div>
</div>

Introduction
The common approach
Blank canvas approach
Steps
Conclusion
Widget code for reference
Back to Top
Back to Top
Back to Top
Back to Top
Back to Top
Back to Top
Back to Top
Back to Top