GA4 + Palm API with Google App script


Guess what? There’s yet another Generative Artificial Intelligence (AI) out its its kind cool. The team at Google, is behind this new AI tool and I managed to get access to it. So I want to introduce you to something called PALM API (which stands for ‘Programmable Actions by Learning from Multimodal demonstrations,’ feel free to forget that technical jargon.). Part of what makes this so amazing is MakerSuite, and now we’re in for some serious changes in how we use AI. So, this article is going to give you a taste of what you will be able to do with Generative AI with Google’s PALM API and MakerSuite in the near future.

Palm API can help me do some pretty amazing things. It just might make my day a lot easer and it works with a number of different programing languages. In this post I am going to show you how to use it directly though App Script.

What is Generative AI?

Generative AI falls within the realm of artificial intelligence and employs machine learning models to create data that closely resembles the input data it has received. This facet of AI has the capability to generate distinct content, encompassing text, images, audio, and even video, relying on its acquired knowledge and training. Whether it’s crafting visual art, composing musical pieces, crafting written content, or even conceptualizing product designs, Generative AI is ushering in an era marked by fresh waves of creativity and innovative possibilities.

Examples

Lets consider a few examples. What if I was creating an app (which I am) that extracts data from Google Analytics GA4. The user types the following

Show me city and event name dimensions and the active user metric for my google analytics property 250796939 from June to august

In order to request some data from the API I need some information like. property id, start and end dates, as well as what dimensions and metrics the user wants to see. Now I could parse this myself with code and it might work, it might not and the code would probably be ugly.

But what if I could make a prompt for PALM API and have it return a JSon object that I need to make my request to the Google Analytics API. Well that’s exactly what I have done and here is the output from the Palm API.


```json 
{ 
  "property_id" : "250796939", 
  "start_date": "2023-06-01", 
  "end_date" : "2023-08-31",    
  "dimensions": ["city", "eventName"], 
  "metrics" : ["activeUsers"] 
} 
``` 

Accessing PALM API and Makersuite

In the following example you will see how to build the POST body for the request and how to send it along with your API key to the endpoint. The trick was finding the response within the JSon returned there can be more then one candidate returned. I normally just grab the first one.

App Script Palm API

The following code makes a request to Palm API submitting the natural language request that the user made and the current date.

function prompt_v1(date, prompt ){

  var dimenisons = "country, eventName, city, audienceName"
  var metrics = "activeUsers, eventCount, screenPageViews"

  var json = {
    "property_id" : "",
    "startdate": "",
    "enddate" : "",   
    "dimensions": ["one", "two"],
    "metrics" : ["three", "four"]
  }


  var text = "The current date is '"+ date + "'. Create a JSon object which contains five parameter's dimension, metrics, start_date, end_date and property_id.  The dimension and metric  parameter's will be comma separated strings they can be empty if there is no valid text for it. The value of the dimension parameter should be a comma separated string of these dimensions names 'country, eventName, city, audienceName' and the value of the metric parameter should be a comma separated string of these metric names 'activeUsers, eventCount, screenPageViews',  the property_id field will also be a string it will be a large number,  start date and end date must be in the following format YYYY-MM-DD, which can be found  in the given this text text  '" + prompt + "'. If no start date is found use set it to seven days ago and if no end date is found set it to today."

  return text 
}

Palm then returns to me my JSon string. I then use that to build the report which I can then send to the Google Analytics data API. In the following code I take what was returned by palm and I send it off to the Google Analytics data API.

function loadGA(report_data){
 
 try {      

      Logger.log(report_data);     

      // create sheet for client
      // var dimensions = report_data.dimension.split(",");
      // var metrics = report_data.metrics.split(",");
      var mergedArray = report_data.dimensions.concat(report_data.metrics)

      Logger.log(mergedArray)
      createSheetIfNotExist(report_data.property_id, mergedArray)      

      // Request data.
      var results = runReport(report_data)
      // clean up the report
      parse_report(report_data.property_id, results)

  } catch (f) {
      Logger.log(f.message);
  }

}

Google Analytics code

This is the standard code I use to send requests to Google analytics data API from App script.

/**
 * Runs a report of a Google Analytics 4 property ID. Creates a sheet with the
 * report.
 */
function runReport(request_data) {
    /**
     * TODO(developer): Uncomment this variable and replace with your
     *   Google Analytics 4 property ID before running the sample.
     */
    const propertyId = request_data.property_id;
    const request = AnalyticsData.newRunReportRequest();
    request.dimensions = [];
    request.metrics = [];
    
    try {

        // Parse metrics      
        request_data.metrics.forEach(function(value) {
          var item = AnalyticsData.newMetric();
          item.name = value.trim().replace("_","");
          request.metrics.push(item) 
          Logger.log(value);
        });

        // parse dimensions
        request_data.dimensions.forEach(function(value) {
          var item = AnalyticsData.newDimension();
          item.name = value.trim().replace("_","");
          request.dimensions.push(item) 
          Logger.log(value);
        });   
        
        // Parse date range
        const dateRange = AnalyticsData.newDateRange();
        dateRange.startDate = request_data.start_date;
        dateRange.endDate = request_data.end_date;      
        request.dateRanges = dateRange;

        // Set limit to 10 becouse its a lot of data.
        request.limit = 10

        const report = AnalyticsData.Properties.runReport(request,
            'properties/' + propertyId);
        if (!report.rows) {
          console.log('No rows returned.');
          return;
        }
        return report
      
    } catch (e) {

        console.log('Failed with error: %s', e);
    }

}

function parse_report(property_id, report){
    
    Logger.log("Writeing data for property Id: " + property_id)     
    report.rows.forEach(function(data) {        
      var row = []

      if (data.dimensionValues != null) {
        data.dimensionValues.forEach(function(item) {      
          row.push(item.value)    
          });
      }
      data.metricValues.forEach(function(item) {      
        row.push(item.value)    
        });
      insertRow(property_id, row)
    });
}

Conclusion

This is early days with this project. It is working very nicely right now. I just wanted to give you a taste so that you can see what I have done and what I am currently working on.

I am going to be putting out some more Google analytics data API posts shortly what would you like to see.


About Linda Lawton

My name is Linda Lawton I have more than 20 years experience working as an application developer and a database expert. I have also been working with Google APIs since 2012 and I have been contributing to the Google .Net client library since 2013. In 2013 I became a a Google Developer Experts for Google Analytics.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.