mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
Add google analytics module
This commit is contained in:
parent
4f8a4c9dc2
commit
ae61d2f7ad
93
modules/googleanalytics/client.go
Normal file
93
modules/googleanalytics/client.go
Normal file
@ -0,0 +1,93 @@
|
||||
package googleanalytics
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/wtfutil/wtf/utils"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
ga "google.golang.org/api/analyticsreporting/v4"
|
||||
)
|
||||
|
||||
type websiteReport struct {
|
||||
Name string
|
||||
Report *ga.GetReportsResponse
|
||||
}
|
||||
|
||||
func (widget *Widget) Fetch() ([]websiteReport) {
|
||||
secretPath, err := utils.ExpandHomeDir(widget.settings.secretFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to parse secretFile path")
|
||||
}
|
||||
|
||||
service, err := makeReportService(secretPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to create Google Analytics Reporting Service")
|
||||
}
|
||||
|
||||
visitorsDataArray := getReports(service, widget.settings.viewIds, widget.settings.months)
|
||||
return visitorsDataArray
|
||||
}
|
||||
|
||||
func makeReportService(secretPath string) (*ga.Service, error) {
|
||||
clientSecret, err := ioutil.ReadFile(secretPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to read secretPath. %v", err)
|
||||
}
|
||||
|
||||
jwtConfig, err := google.JWTConfigFromJSON(clientSecret, ga.AnalyticsReadonlyScope)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to get config from JSON. %v", err)
|
||||
}
|
||||
|
||||
var netClient *http.Client
|
||||
netClient = jwtConfig.Client(oauth2.NoContext)
|
||||
svc, err := ga.New(netClient)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Google Analytics Reporting Service")
|
||||
}
|
||||
|
||||
return svc, err
|
||||
}
|
||||
|
||||
func getReports(service *ga.Service, viewIds map[string]interface{}, displayedMonths int) ([]websiteReport) {
|
||||
startDate := fmt.Sprintf("%s-01", time.Now().AddDate(0, -displayedMonths+1, 0).Format("2006-01"))
|
||||
var websiteReports []websiteReport = nil
|
||||
|
||||
for website, viewId := range viewIds {
|
||||
// For custom queries: https://ga-dev-tools.appspot.com/dimensions-metrics-explorer/
|
||||
|
||||
req := &ga.GetReportsRequest{
|
||||
ReportRequests: []*ga.ReportRequest{
|
||||
{
|
||||
ViewId: viewId.(string),
|
||||
DateRanges: []*ga.DateRange{
|
||||
{StartDate: startDate, EndDate: "today"},
|
||||
},
|
||||
Metrics: []*ga.Metric{
|
||||
{Expression: "ga:sessions"},
|
||||
},
|
||||
Dimensions: []*ga.Dimension{
|
||||
{Name: "ga:month"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
response, err := service.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,}
|
||||
websiteReports = append(websiteReports, report)
|
||||
}
|
||||
return websiteReports
|
||||
}
|
54
modules/googleanalytics/display.go
Normal file
54
modules/googleanalytics/display.go
Normal file
@ -0,0 +1,54 @@
|
||||
package googleanalytics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (widget *Widget) createTable(websiteReports []websiteReport) (string) {
|
||||
content := widget.createHeader()
|
||||
|
||||
for _, websiteReport := range websiteReports {
|
||||
websiteRow := ""
|
||||
|
||||
for _, report := range websiteReport.Report.Reports {
|
||||
websiteRow += fmt.Sprintf(" %-20s", websiteReport.Name)
|
||||
reportRows := report.Data.Rows
|
||||
noDataMonth := widget.settings.months - len(reportRows)
|
||||
|
||||
// Fill in requested months with no data from query
|
||||
if noDataMonth > 0 {
|
||||
websiteRow += strings.Repeat("- ", noDataMonth)
|
||||
}
|
||||
|
||||
if reportRows == nil {
|
||||
websiteRow += fmt.Sprintf("No data found for given ViewId.")
|
||||
} else {
|
||||
for _, row := range reportRows {
|
||||
metrics := row.Metrics
|
||||
|
||||
for _, metric := range metrics {
|
||||
websiteRow += fmt.Sprintf("%-10s", metric.Values[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
content += websiteRow + "\n"
|
||||
}
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
func (widget *Widget) createHeader() (string) {
|
||||
// Creates the table header of consisting of Months
|
||||
currentMonth := int(time.Now().Month())
|
||||
widgetStartMonth := currentMonth-widget.settings.months+1
|
||||
header := " "
|
||||
|
||||
for i := widgetStartMonth; i < currentMonth+1; i++ {
|
||||
header += fmt.Sprintf("%-10s", time.Month(i))
|
||||
}
|
||||
header += "\n"
|
||||
|
||||
return header
|
||||
}
|
29
modules/googleanalytics/settings.go
Normal file
29
modules/googleanalytics/settings.go
Normal file
@ -0,0 +1,29 @@
|
||||
package googleanalytics
|
||||
|
||||
import (
|
||||
"github.com/olebedev/config"
|
||||
"github.com/wtfutil/wtf/cfg"
|
||||
)
|
||||
|
||||
const defaultTitle = "Google Analytics"
|
||||
|
||||
type Settings struct {
|
||||
common *cfg.Common
|
||||
|
||||
months int
|
||||
secretFile string `help:"Your Google client secret JSON file." values:"A string representing a file path to the JSON secret file."`
|
||||
viewIds map[string]interface{}
|
||||
}
|
||||
|
||||
func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings {
|
||||
|
||||
settings := Settings{
|
||||
common: cfg.NewCommonSettingsFromModule(name, defaultTitle, ymlConfig, globalConfig),
|
||||
|
||||
months: ymlConfig.UInt("months"),
|
||||
secretFile: ymlConfig.UString("secretFile"),
|
||||
viewIds: ymlConfig.UMap("viewIds"),
|
||||
}
|
||||
|
||||
return &settings
|
||||
}
|
29
modules/googleanalytics/widget.go
Normal file
29
modules/googleanalytics/widget.go
Normal file
@ -0,0 +1,29 @@
|
||||
package googleanalytics
|
||||
|
||||
import (
|
||||
"github.com/rivo/tview"
|
||||
"github.com/wtfutil/wtf/wtf"
|
||||
)
|
||||
|
||||
type Widget struct {
|
||||
wtf.TextWidget
|
||||
|
||||
settings *Settings
|
||||
}
|
||||
|
||||
func NewWidget(app *tview.Application, settings *Settings) *Widget {
|
||||
widget := Widget{
|
||||
TextWidget: wtf.NewTextWidget(app, settings.common, false),
|
||||
|
||||
settings: settings,
|
||||
}
|
||||
|
||||
return &widget
|
||||
}
|
||||
|
||||
func (widget *Widget) Refresh() {
|
||||
websiteReports := widget.Fetch()
|
||||
contentTable := widget.createTable(websiteReports)
|
||||
|
||||
widget.Redraw(widget.CommonSettings().Title, contentTable, false)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user