LED – Youtube Counter + Google Analytics (update)

Intro

In a previous post I’ve turned a 64×32 LED Matrix into a Youtube subscriber counter and Google Analytics realtime user counter. Since it only gave me two statistics (number of Youtube subscribers and realtime website users) i wanted to improve upon that and let Google Analytics retrieve more information about the realtime users of my website.

To achieve this i needed to rewrite the PHP and Arduino. Previously two Integers were sufficient, but now i need arrays in JSON format to hold all the data.

PHP

Google Analytics API

Since there is no Google Analytics library for Arduino i use HTTPClient for Arduino to execute a PHP script which i’ve hosted on my website. This will request all of the values i need and return it in JSON format.

Head over to Google UA Query Explorer and login to your Analytics account. On this site you can test which metrics or dimensions you want to retrieve. In this example i’m going to use three metrics (activeUsers, sessions and pageviews) and thee dimensions for metric activeUsers. (country, city and pageTitle)

Go to Google APIs Github page and follow the instruction on howto install the library onto your website. Then create an empty PHP document using your favorite editor. (i’m using Visual Studio Code)

Analytics object

First thing we’ll need to do is create an Analytics object and initialize it.

<?php
require 'google-api-php-client/vendor/autoload.php';
function initializeAnalytics(){
  $client = new Google_Client();
  $client->setApplicationName("matrix");
  $client->setAuthConfig(__DIR__ . '/service-key.json');
  $client->setScopes(['https://www.googleapis.com/auth/analytics.readonly']);
  $analytics = new Google_Service_Analytics($client);
  return $analytics;
}

$analytics = initializeAnalytics();

Metrics and dimensions

Then define the metrics and dimensions we want to retrieve from Google Analytics

try {

// Get active users and country + city + page visited
$activeUsersParams = array(
  'dimensions' => 'ga:country,ga:city,ga:pageTitle'
);
$activeUsers = $analytics->data_realtime->get(
    'ga:209758760',
    'rt:activeUsers',
    $activeUsersParams);

// Get total session and pageviews over the last N days
$sessions = $analytics->data_ga->get(
  'ga:209758760',
  date("j", strtotime('-1 day')) . 'daysAgo',
  'today',
  'ga:sessions,ga:pageviews');

You can see that I’ve used the previously mentioned metrics and dimensions. activeUsers will retrieve the country, city and pageTitle value of currently active user on my website while sessions will retrieve the amount of sessions and pageviews for a certain time period. I wanted this start date to be the beginning of each month so that resulted in requesting the current day of the month (date(“j”)) minus one day since the end date is today.

Store values

Next we will make the actual request and store the values.

  $activeUserCount = $activeUsers->totalsForAllResults['rt:activeUsers'];
  $rowsactiveUsers = $activeUsers->getRows();
  $totalSessions = $sessions->totalsForAllResults;

Active user array

Then we check if there is an active user and loop through the values storing each active user in an array and passing it to json_encode

  if($activeUserCount > 0) {
    $data = array (
      'activeusers' => array(),
      'totalsessions' => (int)$totalSessions['ga:sessions'],
      'totalpageviews' => (int)$totalSessions['ga:pageviews']
    );
  
    foreach( $rowsactiveUsers as $rowactiveUser ) {
      $data['activeusers'][] = array(
        'country'   => $rowactiveUser[0],
        'city'  => $rowactiveUser[1],
        'page' => $rowactiveUser[2] = substr($rowactiveUser[2], 0, strpos($rowactiveUser[2], " - Wim van"))
      );
    }
    echo json_encode($data);
    } 

Since my site is running WordPress i needed to strip of the trailing part of the page title. As you can see the page value strips of everything after ” – Wim van”

No active user array

If there are no users active then we’ll execute the following part of the code. No need to retrieve country, city and pageTitle dimensions.

    else {
      $data = array (
        'activeusers' => array(),
        'totalsessions' => (int)$totalSessions['ga:sessions'],
        'totalpageviews' => (int)$totalSessions['ga:pageviews']
      );
    echo json_encode($data);
  }

Exception handler

And finally an error exception handler

} catch (apiServiceException $e) {
  // Handle API service exceptions.
  $error = $e->getMessage();
}

?>

JSON response

Go ahead and upload this to your website and fire up a webbrowser to execute the PHP script. If all went okay you should end up with something similar to this JSON output

{
"activeusers":[
{
"country":"Netherlands",
"city":"Amsterdam",
"page":"Telfort naar KPN Migratie"
},
{
"country":"Netherlands",
"city":"Dordrecht",
"page":"Youtube PTZ Control by Chatbot"
}
],
"totalsessions":5109,
"totalpageviews":15587
}

So there is an activeuser object which holds an array of objects (country, city and page from every active user) and two other keys (totalsessions and totalpageviews) .

Next up we’re going to interpret this JSON output in Arduino to display it on the LED Matrix panel.

Arduino

Now we’ve got our Google Analytics response in JSON format we’re ready to move on to the Arduino part for parsing the JSON values and Youtube subscriber count. I’ll cover the most important parts of the code and will provide a download link at the end of this article.

Libraries

First we’ll need to import a couple of libraries

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PxMatrix.h>
#include <YoutubeApi.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>
  • WiFi and WifiClientSecure for connecting the Wemos D1 Mini to a wireless network
  • PxMatrix for driving the LED Matrix
  • YoutubeAPI for retrieving the Youtube subscriber count
  • ArduinoJson for parsing the JSON input
  • HTTPClient for connecting to the previously created PHP script

Variables

Next a couple of variables.

const char* ssid = "your_ssid";
const char* password = "your_wpa2";
#define API_KEY "your_api_key"
#define CHANNEL_ID "your_channel_id"

unsigned long api_mtbs = 60000;
unsigned long api_lasttime = 60000;

long subs = 0;
long totalSessions = 0;
long totalPageviews = 0;
String scrollTop = "";
String scrollBottom = "";
int currentPageviews = 0;
  • SSID of your wireless network
  • WPA2 key of your wireless network
  • API_KEY you created in Google Developers Console for your project
  • Youtube channel ID
  • api_mtbs and lasttime is the time between requests
  • subs, totalSessions, totalPageviews and currentPageviews initially set to zero
  • scrollTop string to hold information about country and city
  • scrollBottom string to hold information about page visited

PxMatrix

Define the dimensions of the PxMatrix display

PxMATRIX display(64,32,P_LAT, P_OE,P_A,P_B,P_C,P_D,P_E);

Colors

Create a couple of standard colors we’ll intent to use

uint16_t myRED = display.color565(255, 0, 0);
uint16_t myGREEN = display.color565(0, 255, 0);
uint16_t myBLUE = display.color565(0, 0, 255);
uint16_t myWHITE = display.color565(255, 255, 255);
uint16_t myYELLOW = display.color565(255, 255, 0);
uint16_t myCYAN = display.color565(0, 255, 255);
uint16_t myMAGENTA = display.color565(255, 0, 255);
uint16_t myBLACK = display.color565(0, 0, 0);
uint16_t myORANGE = display.color565(255, 125, 0);
uint16_t myGREY = display.color565(125, 125, 125);

uint16_t myCOLORS[10]={myRED,myGREEN,myBLUE,myWHITE,myYELLOW,myCYAN,myMAGENTA,myBLACK,myORANGE,myGREY};

Icons

Convert two images to hex using this site. Keep in mind that you need to scale down each image in order to fit on the screen. The maximum resolution of each image can be 64×32 since that is the resolution the display is using. My images are both 21×14 large.

Youtube Icon

uint16_t static youtube_icon[]={
0x0000, 0x0000, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x0010 (16) pixels
0xF800, 0xF800, 0xF800, 0x0000, 0x0000, 0x0000, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x0020 (32) pixels
0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0x0000, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x0030 (48) pixels
0xF800, 0xF800, 0xFFFF, 0xFFFF, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x0040 (64) pixels
0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xFFFF, 0xFFFF, 0xFFFF, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x0050 (80) pixels
0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,   // 0x0060 (96) pixels
0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x0070 (112) pixels
0xF800, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x0080 (128) pixels
0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x0090 (144) pixels
0xF800, 0xF800, 0xF800, 0xF820, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,   // 0x00A0 (160) pixels
0x0000, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x00B0 (176) pixels
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x00C0 (192) pixels
0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x00D0 (208) pixels
0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xFFFF, 0xFFFF, 0x0000, 0xF800, 0xF800, 0xF800,   // 0x00E0 (224) pixels
0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0x0000,   // 0x00F0 (240) pixels
0x0000, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0x0000, 0xF800, 0xF800, 0xF800,   // 0x0100 (256) pixels
0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x0110 (272) pixels
0x0000, 0x0000, 0x0000, 0xF861, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800, 0xF800,   // 0x0120 (288) pixels
0xF800, 0xF800, 0xF800, 0xF820, 0x0000, 0x0000,
};

Analytics Icon

uint16_t static  analytics_icon[]={
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFB20,   // 0x0010 (16) pixels
0xFB20, 0xFB20, 0xFB20, 0xFB20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,   // 0x0020 (32) pixels
0x0000, 0x0000, 0x0000, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,   // 0x0030 (48) pixels
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0x0000,   // 0x0040 (64) pixels
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFB20, 0xFB20, 0xFB20,   // 0x0050 (80) pixels
0xFB20, 0xFB20, 0xFB20, 0xFB20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,   // 0x0060 (96) pixels
0x0000, 0x0000, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,   // 0x0070 (112) pixels
0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0x0000, 0x0000,   // 0x0080 (128) pixels
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFB20, 0xFB20, 0xFB20, 0xFB20,   // 0x0090 (144) pixels
0xFB20, 0xFB20, 0xFB20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60,   // 0x00A0 (160) pixels
0xFE60, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFE60,   // 0x00B0 (176) pixels
0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0x0000, 0xFE60, 0xFE60,   // 0x00C0 (192) pixels
0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20,   // 0x00D0 (208) pixels
0xFB20, 0xFB20, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60,   // 0x00E0 (224) pixels
0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60,   // 0x00F0 (240) pixels
0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFE60, 0xFE60, 0xFE60, 0xFE60,   // 0x0100 (256) pixels
0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20,   // 0x0110 (272) pixels
0xFB20, 0x0000, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFE60, 0xFB20,   // 0x0120 (288) pixels
0xFB20, 0xFB20, 0xFB20, 0xFB20, 0xFB20, 0x0000,

Setup function

Next we create the setup function

void setup() {

  Serial.begin(115200);

  WiFi.mode(WIFI_STA); 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
 
  Serial.println("Connected to the WiFi network");
  client.setInsecure();

  display.begin(16);
  display.setFastUpdate(true);
  display.clearDisplay();
  display.setTextColor(myORANGE);
  display.setCursor(2, 1);
  display.print("Connecting");
  display.setTextColor(myORANGE);
  display.setCursor(2, 9);
  display.print("to");
  display.setTextColor(myWHITE);
  display.setCursor(2, 17);
  display.setTextSize(2);
  display.print(ssid);

  display_update_enable(true);
  
  delay(3000);

}

Pretty self explanatory, the serial port is opened and the connection to the wireless network is made. Then the display is initiated and the text Connecting to <network name> is printed to the screen in two different colors and three different positions.

Displaytext function

Now we’re ready to create a couple of function that will actually print the text on the display and are called from other function further along in the program. The first one is displayText

void displayText(String text, int yPos, int textSize) {
  int16_t  x1, y1;
  uint16_t w, h;
  display.setTextSize(textSize);
  char charBuf[text.length() + 1];
  text.toCharArray(charBuf, text.length() + 1);
  display.getTextBounds(charBuf, 0, yPos, &x1, &y1, &w, &h);
  int startingX = 24;
  if (startingX < 0) {
    display.setTextSize(1);
    display.getTextBounds(charBuf, 0, yPos, &x1, &y1, &w, &h);
    startingX = 24 - (w / 2);
  }
  display.setCursor(startingX, yPos);
  display.print(text);
}

This function takes in three parameters. A string called text which holds the text value we want to print to the display. The yPos position this string has to be positioned on the display and the text size. Since my images are 21 pixels wide and they are displayed at pixel 1 from the left of the display, startingX would be 1+21+2(empty space between image and text) = 24.

Updatescreen function

The displayText function is called from within the updateScreen function.

void updateScreen(long subCount, long sessionCount, long pageCount) {
  display.clearDisplay();
  draw_youtube_icon(1, 1);
  draw_analytics_icon(1, 17);
  display.setTextColor(myWHITE);
  displayText(String(subCount), 1, 2);
  displayText("S:" + String(sessionCount), 17, 1);
  displayText("P:" + String(pageCount), 24, 1);
}

This function takes in Youtube subscriber number and Google Analytics session and page counter and passes it along to the displayText function. It also draws both the Youtube and Anaytics images by calling draw_youtube_icon and draw_analytics_icon.

Draw Youtube icon function

void draw_youtube_icon (int x, int y)
{
  int counter = 0;
  for (int yy = 0; yy < 14; yy++)
  {
    for (int xx = 0; xx < 21; xx++)
    {
      display.drawPixel(xx + x , yy + y, youtube_icon[counter]);
      counter++;
    }
  }
}

Draw Analytics icon function

void draw_analytics_icon (int x, int y)
{
  int counter = 0;
  for (int yy = 0; yy < 14; yy++)
  {
    for (int xx = 0; xx < 21; xx++)
    {
      display.drawPixel(xx + x , yy + y, analytics_icon[counter]);
      counter++;
    }
  }
}

So what’s happening here is that both functions loop through the previously defined image hex code and draws them to the display for the resolution of 21 x 14.

Scroll double text function

Next up is the scroll_double_text function.

void scroll_double_text(uint8_t ypos_top, uint8_t ypos_bottom, unsigned long scroll_delay, String text_top, String text_bottom)
{
    uint16_t text_top_length = text_top.length();
    uint16_t text_bottom_length = text_bottom.length();
    uint16_t text_length_max = max(text_top_length,text_bottom_length);
    display.setTextWrap(false);
    display.setTextSize(2);
    display.setRotation(0);
    display.setTextColor(myWHITE);

    // Asuming 10 pixel average character width + 1 more to get to let the scroll fully finish
    for (int xpos=matrix_width; xpos>-(matrix_width+text_length_max*11); xpos--)
    {
      display.clearDisplay();
      display.setTextColor(myORANGE);
      display.setCursor(xpos,ypos_top);
      display.println(text_top);
      display.setTextColor(myWHITE);
      display.setCursor(xpos+5,ypos_bottom);
      display.println(text_bottom);
      delay(scroll_delay);
      yield();

      delay(scroll_delay/5);
      yield();
    }
}

This function takes in y position for both the top and bottom text, the scroll delay and the string value for both the top and bottom. It then looks at both top and bottom strings and determines which is longer and grabs the character length of that string which it will use later on to ensure that it will finish scrolling to the last character. Then it will clear the display and print both top and bottom text in two different colors the display, where the bottom text is 5 pixels ‘behind’ the top text.

Main loop function

The main loop function is the next function i will cover and this will check for the amount of current Youtube subscribers and retrieve the Google Analytics values through the previously created PHP script.

void loop(){
  if (millis() - api_lasttime > api_mtbs)  {
    if (api.getChannelStatistics(CHANNEL_ID))
    {
      Serial.println("---------Stats---------");
      Serial.print("Subscriber Count: ");
      Serial.println(api.channelStats.subscriberCount);
      subs = api.channelStats.subscriberCount;      
    }

    HTTPClient http; 
    http.begin("https://yoursite.com/analytics.php");
    int httpCode = http.GET(); 
    if (httpCode > 0) { 
        String payload = http.getString();

        StaticJsonDocument<384> doc;
        
        DeserializationError error = deserializeJson(doc, payload);
        
        if (error) {
          Serial.print(F("deserializeJson() failed: "));
          Serial.println(error.f_str());
          return;
        }

        Serial.print("Total Sessions: ");
        Serial.println(doc["totalsessions"].as<int>());
        totalSessions = doc["totalsessions"].as<int>();
        Serial.print("Total Pageviews: ");
        Serial.println(doc["totalpageviews"].as<int>());
        totalPageviews = doc["totalpageviews"].as<int>();
        Serial.print("Active Users: ");
        Serial.println(doc["activeusers"].size());

        if (doc["activeusers"].size() > 0) {
          scrollTop = "";
          scrollBottom = "";
  
          for (JsonObject user : doc["activeusers"].as<JsonArray>()) {
          Serial.print("Country: ");
          Serial.println(user["country"].as<const char*>());
          scrollTop = user["country"].as<String>();
          Serial.print("City: ");
          Serial.println(user["city"].as<const char*>());
          scrollTop += " - " + user["city"].as<String>();
          Serial.print("Page: ");
          Serial.println(user["page"].as<const char*>());
          scrollBottom += user["page"].as<String>();

          if (currentPageviews < totalPageviews) {
            Serial.print("Current Pageviews: ");
            Serial.println(currentPageviews);
            Serial.print("Total Pageviews: ");
            Serial.println(totalPageviews);
            scroll_double_text(1,16,50,scrollTop,scrollBottom);
            currentPageviews = totalPageviews;
          }          
  
        }

        }

      } 
    else {
      Serial.println("Error on HTTP request");
    } 
    http.end();
       
    api_lasttime = millis();
    updateScreen(subs, totalSessions, totalPageviews);
  }
}

When entering the loop it checks if the time between the previous request exceeds the amount of time we’ve set at the variable at the top of the program. (60000) If that is True then it will execute the Youtube API and retrieve the current subscriber count of your Youtube channel and stores it in the subs variable.

Then the HTTPClient is initiated and will get the response of the Google Analytics PHP script we’ve created and stores it in the payload object. ArduinoJson will create an empty JSON document (StaticJsonDocument) and deserialize it and pass it of to be iterated. Now we can extract the values we seek like, totalSession and totalPageviews etc.

We actually have two types of request

  • No active user on the site, only display Youtube susbscriber numer and Total Sessions and Total Pageviews
  • Active user on the site, in addition to the previous request we also want to retrieve the County, City and Page Title from that active user.

IF there is an active user on the site the activeuser array is larger than 0 and we execute some additional code. Loop through the activeuser array and retrieve all the activeuser array and pull the objects which each contain:

  • Country
  • City
  • Page Title

Store it in the user array. Followed by executing the scroll_double_text function with scrollTop and scrollBottom as arguments to print those values to the display.

The last IF statement checks if the active users on the site clicks another page so that the totalPageviews integer variable increases and we can also display this page visited to the display.

Finally close the HTTPClient and set api_lasttime to current time and execute updateScreen function to display the default state of the display showing the Youtube and Analytics icon with next to them Youtube subscriber count and Total Session / Total Pageviews.

en_USEnglish