github.com/wtfutil/wtf@v0.43.0/modules/googleanalytics/client.go (about) 1 package googleanalytics 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 "net/http" 8 "os" 9 "path/filepath" 10 "time" 11 12 "github.com/wtfutil/wtf/utils" 13 "golang.org/x/oauth2/google" 14 gaV3 "google.golang.org/api/analytics/v3" 15 gaV4 "google.golang.org/api/analyticsreporting/v4" 16 "google.golang.org/api/option" 17 ) 18 19 type websiteReport struct { 20 Name string 21 Report *gaV4.GetReportsResponse 22 RealtimeReport *gaV3.RealtimeData 23 } 24 25 func (widget *Widget) fetch() []websiteReport { 26 secretPath, err := utils.ExpandHomeDir(widget.settings.secretFile) 27 if err != nil { 28 log.Fatalf("Unable to parse secretFile path") 29 } 30 31 serviceV4, err := makeReportServiceV4(secretPath) 32 if err != nil { 33 log.Fatalf("Unable to create v3 Google Analytics Reporting Service") 34 } 35 36 var serviceV3 *gaV3.Service 37 if widget.settings.enableRealtime { 38 serviceV3, err = makeReportServiceV3(secretPath) 39 if err != nil { 40 log.Fatalf("Unable to create v3 Google Analytics Reporting Service") 41 } 42 } 43 44 visitorsDataArray := getReports( 45 serviceV4, widget.settings.viewIds, widget.settings.months, serviceV3, 46 ) 47 return visitorsDataArray 48 } 49 50 func buildNetClient(secretPath string) *http.Client { 51 clientSecret, err := os.ReadFile(filepath.Clean(secretPath)) 52 if err != nil { 53 log.Fatalf("Unable to read secretPath. %v", err) 54 } 55 56 jwtConfig, err := google.JWTConfigFromJSON(clientSecret, gaV4.AnalyticsReadonlyScope) 57 if err != nil { 58 log.Fatalf("Unable to get config from JSON. %v", err) 59 } 60 61 return jwtConfig.Client(context.Background()) 62 } 63 64 func makeReportServiceV3(secretPath string) (*gaV3.Service, error) { 65 client := buildNetClient(secretPath) 66 67 svc, err := gaV3.NewService(context.Background(), option.WithHTTPClient(client)) 68 if err != nil { 69 log.Fatalf("Failed to create v3 Google Analytics Reporting Service") 70 } 71 72 return svc, err 73 } 74 75 func makeReportServiceV4(secretPath string) (*gaV4.Service, error) { 76 client := buildNetClient(secretPath) 77 svc, err := gaV4.NewService(context.Background(), option.WithHTTPClient(client)) 78 if err != nil { 79 log.Fatalf("Failed to create v4 Google Analytics Reporting Service") 80 } 81 82 return svc, err 83 } 84 85 func getReports( 86 serviceV4 *gaV4.Service, viewIds map[string]interface{}, displayedMonths int, serviceV3 *gaV3.Service, 87 ) []websiteReport { 88 startDate := fmt.Sprintf("%s-01", time.Now().AddDate(0, -displayedMonths+1, 0).Format("2006-01")) 89 var websiteReports []websiteReport 90 91 for website, viewID := range viewIds { 92 // For custom queries: https://ga-dev-tools.appspot.com/dimensions-metrics-explorer/ 93 94 req := &gaV4.GetReportsRequest{ 95 ReportRequests: []*gaV4.ReportRequest{ 96 { 97 ViewId: viewID.(string), 98 DateRanges: []*gaV4.DateRange{ 99 {StartDate: startDate, EndDate: "today"}, 100 }, 101 Metrics: []*gaV4.Metric{ 102 {Expression: "ga:sessions"}, 103 }, 104 Dimensions: []*gaV4.Dimension{ 105 {Name: "ga:month"}, 106 }, 107 }, 108 }, 109 } 110 response, err := serviceV4.Reports.BatchGet(req).Do() 111 112 if err != nil { 113 log.Fatalf("GET request to analyticsreporting/v4 returned error with viewID: %s", viewID) 114 } 115 if response.HTTPStatusCode != 200 { 116 log.Fatalf("Did not get expected HTTP response code") 117 } 118 119 report := websiteReport{Name: website, Report: response} 120 if serviceV3 != nil { 121 report.RealtimeReport = getLiveCount(serviceV3, viewID.(string)) 122 } 123 websiteReports = append(websiteReports, report) 124 } 125 return websiteReports 126 } 127 128 func getLiveCount(service *gaV3.Service, viewID string) *gaV3.RealtimeData { 129 res, err := service.Data.Realtime.Get("ga:"+viewID, "rt:activeUsers").Do() 130 if err != nil { 131 log.Fatalf("Failed to fetch real time data for view ID %s: %v. Have you enrolled in the real time beta? If not, do so here: https://docs.google.com/forms/d/1qfRFysCikpgCMGqgF3yXdUyQW4xAlLyjKuOoOEFN2Uw/viewform", viewID, err) 132 } 133 134 return res 135 }