1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00
Casey Primozic d5e06fe0c2
Add support for pulling realtime Google Analytics metrics
* Add config option `enableRealtime` that, if set to true, will cause realtime metrics to be displayed above the historicaly view counts for all view IDs
 * Add in the v3 Google API client and construct a service for it conditionally if realtime metrics are enabled
 * Update google analytics data pulling code to retrieve realtime metrics using the v3 client if realtime metrics are enabled in settings
 * Update table generation code to display fetched realtime metrics if they are available
2019-08-30 18:34:31 -07:00

133 lines
3.4 KiB
Go

package googleanalytics
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"time"
"github.com/wtfutil/wtf/utils"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
gaV3 "google.golang.org/api/analytics/v3"
gaV4 "google.golang.org/api/analyticsreporting/v4"
)
type websiteReport struct {
Name string
Report *gaV4.GetReportsResponse
RealtimeReport *gaV3.RealtimeData
}
func (widget *Widget) Fetch() []websiteReport {
secretPath, err := utils.ExpandHomeDir(widget.settings.secretFile)
if err != nil {
log.Fatalf("Unable to parse secretFile path")
}
serviceV4, err := makeReportServiceV4(secretPath)
if err != nil {
log.Fatalf("Unable to create v3 Google Analytics Reporting Service")
}
var serviceV3 *gaV3.Service
if widget.settings.enableRealtime {
serviceV3, err = makeReportServiceV3(secretPath)
if err != nil {
log.Fatalf("Unable to create v3 Google Analytics Reporting Service")
}
}
visitorsDataArray := getReports(
serviceV4, widget.settings.viewIds, widget.settings.months, serviceV3,
)
return visitorsDataArray
}
func buildNetClient(secretPath string) *http.Client {
clientSecret, err := ioutil.ReadFile(secretPath)
if err != nil {
log.Fatalf("Unable to read secretPath. %v", err)
}
jwtConfig, err := google.JWTConfigFromJSON(clientSecret, gaV4.AnalyticsReadonlyScope)
if err != nil {
log.Fatalf("Unable to get config from JSON. %v", err)
}
return jwtConfig.Client(oauth2.NoContext)
}
func makeReportServiceV3(secretPath string) (*gaV3.Service, error) {
var netClient = buildNetClient(secretPath)
svc, err := gaV3.New(netClient)
if err != nil {
log.Fatalf("Failed to create v3 Google Analytics Reporting Service")
}
return svc, err
}
func makeReportServiceV4(secretPath string) (*gaV4.Service, error) {
var netClient = buildNetClient(secretPath)
svc, err := gaV4.New(netClient)
if err != nil {
log.Fatalf("Failed to create v4 Google Analytics Reporting Service")
}
return svc, err
}
func getReports(
serviceV4 *gaV4.Service, viewIds map[string]interface{}, displayedMonths int, serviceV3 *gaV3.Service,
) []websiteReport {
startDate := fmt.Sprintf("%s-01", time.Now().AddDate(0, -displayedMonths+1, 0).Format("2006-01"))
var websiteReports []websiteReport
for website, viewID := range viewIds {
// For custom queries: https://ga-dev-tools.appspot.com/dimensions-metrics-explorer/
req := &gaV4.GetReportsRequest{
ReportRequests: []*gaV4.ReportRequest{
{
ViewId: viewID.(string),
DateRanges: []*gaV4.DateRange{
{StartDate: startDate, EndDate: "today"},
},
Metrics: []*gaV4.Metric{
{Expression: "ga:sessions"},
},
Dimensions: []*gaV4.Dimension{
{Name: "ga:month"},
},
},
},
}
response, err := serviceV4.Reports.BatchGet(req).Do()
if err != nil {
log.Fatalf("GET request to analyticsreporting/v4 returned error with viewID: %s", viewID)
}
if response.HTTPStatusCode != 200 {
log.Fatalf("Did not get expected HTTP response code")
}
report := websiteReport{Name: website, Report: response}
if serviceV3 != nil {
report.RealtimeReport = getLiveCount(serviceV3, viewID.(string))
}
websiteReports = append(websiteReports, report)
}
return websiteReports
}
func getLiveCount(service *gaV3.Service, viewID string) *gaV3.RealtimeData {
res, err := service.Data.Realtime.Get("ga:"+viewID, "rt:activeUsers").Do()
if err != nil {
log.Fatalf("Failed to fetch realtime data for view ID %s: %v", viewID, err)
}
return res
}