Build a real-time dashboard (web app) using google.script.run API

Polling is bad, period. Falling short of integrating web sockets, this solution comes close to streaming live data.

Build a real-time dashboard (web app) using google.script.run API
Build a real-time dashboard (web app) using google.script.run API

specifically, that's google.script.run.withSuccessHandler & it would be unfair to talk about this without hyping up the setInterval function (you’ll see) 😊

google.script.run is an asynchronous client-side javascript api available in html-service pages that can call server-side apps script functions.

more about it can be found here.

context

if you’re a data buff (or are anal retentive about any kind of information), you’d also have the urge to access that information, as fast as possible. i started exploring ways to display data in real-time while solutioning* a way to show incoming-call related stats in real-time (viz. # of calls that are queued, # of agents who’re engaged/busy on a call, the # of agents who’re free to receive more/new calls etc.).

from what i was able to gather, on a typical web-server and with the usual coding languages, one could simply open live connections via web sockets on the client &/or server side to stream changes, as and when they occur. i don’t yet know if we could achieve a similar architecture with google apps script but afaik, there isn’t one.

prior reading

architecture

server-side

i know this sounds fancy but its simply your code.gs file 😛 where you configure the functions you require, that are able to fetch data from whatever sources you’re storing them in (if any); say - sheets, bigquery etc.

client-side

its the code that runs from your *.html file and, post loading, on your web browser.

client-side setup is rather a tricky one as you'd need to take into account the throttling limitations of external apis (if you're using any) and that of google's itself (i'm yet to figure out what that is, as there haven't been any relevant errors which could point me in that direction).

in my demo script, i've invoked google.script.run.withSuccessHandler twice - one that runs every 10 seconds and the other, every 1 second.

codebase

you can access the entire script on my github repository here or make a copy from the original script - here.

in this dummy setup, i'm fetching random quotes from thesimpsonsquoteapi (thanks to jason luboff's post on freecodecamp.org) along with displaying a timer that changes every second.

server-side

function doGet(e) {
  return HtmlService.createHtmlOutputFromFile('Index').setTitle('Realtime Data');
}

function randomQuotes() {
  var baseURL = 'https://thesimpsonsquoteapi.glitch.me/quotes';
  var quotesData = UrlFetchApp.fetch(baseURL, { muteHttpExceptions: true });
  var quote;
  var imageURL;
  if (quotesData.getResponseCode() == 200 || quotesData.getResponseCode() == 201) {
    var response = quotesData.getContentText();
    var data = JSON.parse(response)[0];
    quote = data["quote"];
    imageURL = data["image"];
  } else {
    quote = 'Random Quote Generator is broken!';
    imageURL = 'https://cdn.shopify.com/s/files/1/1061/1924/products/Sad_Face_Emoji_large.png?v=1480481055';
  }
  var randomQuote = {
    "quote": quote,
    "imageTag": '<img class="responsive-img" src="' + imageURL + '">'
  }
  return randomQuote;
}

function getTime() {
  var now = new Date();
  return now;
}

client-side

highlighting the code pieces that matter the most.

<script>
    function onSuccess1(quoteData) {
        var quoteActual = document.getElementById('quote');
        quoteActual.innerHTML = quoteData.quote;
        var quoteImg = document.getElementById('quoteImage');
        quoteImg.innerHTML = quoteData.imageTag;
    }

    setInterval(function() {
        console.log("getting quote...")
        google.script.run.withSuccessHandler(onSuccess1).randomQuotes();
    }, 10000);
</script>
index.html - fetches random quotes every 10 seconds (10000 ms)
<script>
    function onSuccess2(now) {
        var div = document.getElementById('time');
        var today = new Date();
        var time = today.getHours() + " : " + today.getMinutes() + " : " + today.getSeconds();
        div.innerHTML = time;
    }

    setInterval(function() {
        console.log("getting time...")
        google.script.run.withSuccessHandler(onSuccess2).getTime();
    }, 1000);
</script>
index.html - fetches time every 1 second (1000 ms)

demo

you can access a demo web app hosted on my account here & here's a visual overview -

real-time
real-time
real-time console log
real-time console log

credits

footnote

*solutioning: i wanted to know if this is even a real word. googled it, obviously. found this article and read something that made my day -

I hate it when people utilize paradigms inculcating contra-diminutive words for the ostensible objective of maximizing pretentiousness.