Skip to content

Instantly share code, notes, and snippets.

@ezioruan
Forked from rickt/analyticsdumper.go
Created April 11, 2016 03:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ezioruan/4337b7f0b10aef31060a987cbb4cbfaf to your computer and use it in GitHub Desktop.
Save ezioruan/4337b7f0b10aef31060a987cbb4cbfaf to your computer and use it in GitHub Desktop.
example Go code showing how to download reporting data from Google Analytics using the Core Reporting API, a Google service account + oauth2 (UPDATE: go here http://code.rickt.org/post/142445693275/updated-golang-code-to-query-ga-data-via-the instead)
//
// NOTE: go here for an update http://code.rickt.org/post/142445693275/updated-golang-code-to-query-ga-data-via-the
// this gist still works but has a lot of extra fluff you don't need
// http://code.rickt.org/post/142445693275/updated-golang-code-to-query-ga-data-via-the is what you really want
//
package main
import (
"flag"
"fmt"
"golang.org/x/oauth2"
"golang.org/x/oauth2/jwt"
"google.golang.org/api/analytics/v3"
"io/ioutil"
"log"
"os"
"time"
)
// constants
const (
dateLayout string = "2006-01-02" // date format that Core Reporting API requires
)
// example secretsfile (obtained from the Google Cloud Console specific to your app)
// {
// "web": {
// "auth_uri": "https://accounts.google.com/o/oauth2/auth",
// "token_uri": "https://accounts.google.com/o/oauth2/token",
// "client_email": "blahblahblahblah@developer.gserviceaccount.com",
// "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/blahblahblahblah@developer.gserviceaccount.com",
// "client_id": "blahblahblahblah.apps.googleusercontent.com",
// "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs"
// }
// }
// your globals (change these using values from the JSON secretsfile obtained from the Google Cloud Console specific to your app)
var (
gaServiceAcctEmail string = "blahblahblahblah@developer.gserviceaccount.com" // email address of registered app in Google Cloud Console
gaServiceAcctPEMKey string = "/path/to/your/analyticsdumper.pem" // private key (PEM format) of registered application
gaScope string = "https://www.googleapis.com/auth/analytics.readonly" // scope information for Core Reporting API
gaTableID string = "ga:XXXXXXXX" // namespaced profile (table) ID of your analytics account/property/profile
gaTokenURL string = "https://accounts.google.com/o/oauth2/token" // token auth URL
)
// analytics-dumper globals
var (
// vars used for the runtime flags
gaDimensions string // which dimensions?
gaEndDate string // what's the end date of our query?
gaFilter string // what's our filter (if any)?
gaMetrics string // which metrics?
gaMaxResults int64 // how many max results do we want returned?
gaSortOrder string // what's the sort order?
help bool // do we want help?
gaStartDate string // what's the start date of our query?
)
// func: init()
// initialisation function for the command line flags/options.
func init() {
flag.BoolVar(&help, "h", false, "show all command line arguments.")
flag.StringVar(&gaDimensions, "d", "", "GA query dimensions")
flag.StringVar(&gaEndDate, "ed", "", "GA query end date")
flag.StringVar(&gaFilter, "f", "", "GA query filter")
flag.Int64Var(&gaMaxResults, "x", 10000, "GA maximum # of results to return (default: 10000)")
flag.StringVar(&gaMetrics, "m", "ga:pageviews", "GA metrics you want to query (default: ga:pageviews)")
flag.StringVar(&gaSortOrder, "s", "", "GA query reply sort order")
flag.StringVar(&gaStartDate, "sd", "2013-10-01", "GA query start date (default: 2013-10-01)")
}
// func: main()
// the main function.
func main() {
// grok the command line args
flag.Usage = usage
flag.Parse()
if help {
flag.Usage()
}
// load up the registered applications private PEM key.
pk, err := ioutil.ReadFile(gaServiceAcctPEMKey)
if err != nil {
log.Fatal("error reading GA Service Account PEM key -", err)
}
// create a jwt.Config that we will subsequently use for our authenticated client/transport
jwtc := jwt.Config{
Email: gaServiceAcctEmail,
PrivateKey: pk,
Scopes: []string{gaScope},
TokenURL: gaTokenURL,
}
// create our authenticated client/transport using the jwt.Config we just created
client := jwtc.Client(oauth2.NoContext)
// create a new analytics service by passing in the authenticated http client
analyticsService, err := analytics.New(client)
if err != nil {
log.Fatal("error creating Analytics Service -", err)
}
// create a new analytics data service by passing in the analytics service we just created
dataGaService := analytics.NewDataGaService(analyticsService)
// w00t! now we're talking to the core reporting API. the hard stuff is over, lets setup a simple query.
var dimensions, filter, sortorder string
// if no gaEndDate specified via command line args, set it to today's date.
if gaEndDate == "" {
t := time.Now()
gaEndDate = t.Format(dateLayout)
}
// setup the query, call the Analytics API via our analytics data service's Get func with the table ID, dates & metric variables
dataGaGetCall := dataGaService.Get(gaTableID, gaStartDate, gaEndDate, gaMetrics)
// now we can build the analytics query!
// setup the dimensions (if none specified at runtime)
if gaDimensions != "" {
dimensions = fmt.Sprintf("ga:dimensions=%s", gaDimensions)
dataGaGetCall.Dimensions(dimensions)
}
// setup the sort order (if none specified at runtime)
if gaSortOrder != "" {
sortorder = fmt.Sprintf("ga:sort=%s", gaSortOrder)
dataGaGetCall.Sort(sortorder)
}
// setup the filter (if none specified at runtime)
if gaFilter != "" {
filter = fmt.Sprintf("%s", gaFilter)
dataGaGetCall.Filters(filter)
}
// setup the max results we want returned.
dataGaGetCall.MaxResults(gaMaxResults)
// send the query to the API, get a big fat gaData back.
gaData, err := dataGaGetCall.Do()
if err != nil {
log.Fatal("API error -", err)
}
// we've made it this far, so lets print info about the query
fmt.Printf("gaStartDate=%s, gaEndDate=%s\n", gaStartDate, gaEndDate)
fmt.Printf("gaDimensions=%s\n", dimensions)
fmt.Printf("gaFilter=%s\n", filter)
fmt.Printf("gaMetrics=%s\n", gaMetrics)
fmt.Printf("gaSortOrder=%s\n", sortorder)
// how much data did we get back?
fmt.Printf("len(gaData.Rows)=%d, TotalResults=%d\n", len(gaData.Rows), gaData.TotalResults)
// lets print out the returned data via a lazy loop through the returned rows
for row := 0; row <= len(gaData.Rows)-1; row++ {
fmt.Printf("row=%d %v\n", row, gaData.Rows[row])
}
}
// func: usage()
// prints out all possible flags/options when "-h" or an unknown option is used at runtime.
// exits back to shell when complete.
func usage() {
fmt.Printf("usage: %s [OPTION] \n", os.Args[0])
flag.PrintDefaults()
os.Exit(2)
}
// example run of analyticsdumper below
// note: shows all pageviews for this particular property from 2013-10-01 until date of run
// $ ./analyticsdumper
// gaStartDate=2013-10-01, gaEndDate=2016-04-07
// gaDimensions=
// gaFilter=
// gaMetrics=ga:pageviews
// gaSortOrder=
// len(gaData.Rows)=1, TotalResults=1
// row=0 [646765827]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment