mirror of
https://github.com/Kugelschieber/marvinblum.git
synced 2026-01-18 06:40:27 +00:00
2
go.mod
2
go.mod
@@ -7,7 +7,7 @@ require (
|
|||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/emvi/api-go v0.2.2
|
github.com/emvi/api-go v0.2.2
|
||||||
github.com/emvi/logbuch v1.1.1
|
github.com/emvi/logbuch v1.1.1
|
||||||
github.com/emvi/pirsch v1.5.1
|
github.com/emvi/pirsch v1.5.3-0.20200914194223-a990d20e91a2
|
||||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||||
github.com/golang-migrate/migrate v3.5.4+incompatible
|
github.com/golang-migrate/migrate v3.5.4+incompatible
|
||||||
github.com/golang-migrate/migrate/v4 v4.12.2
|
github.com/golang-migrate/migrate/v4 v4.12.2
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -100,6 +100,10 @@ github.com/emvi/pirsch v1.5.1-0.20200911122906-93d727c607a9 h1:H1+nLRJsBy1ZuhBP4
|
|||||||
github.com/emvi/pirsch v1.5.1-0.20200911122906-93d727c607a9/go.mod h1:GDijqLHM331iWtmDmc7th19RxDrZadRkKoNvd9/kDX8=
|
github.com/emvi/pirsch v1.5.1-0.20200911122906-93d727c607a9/go.mod h1:GDijqLHM331iWtmDmc7th19RxDrZadRkKoNvd9/kDX8=
|
||||||
github.com/emvi/pirsch v1.5.1 h1:HFlR5Ps2mPFqHGkFvEfHLme6beCn5aIpu/fCNz/B43Y=
|
github.com/emvi/pirsch v1.5.1 h1:HFlR5Ps2mPFqHGkFvEfHLme6beCn5aIpu/fCNz/B43Y=
|
||||||
github.com/emvi/pirsch v1.5.1/go.mod h1:GDijqLHM331iWtmDmc7th19RxDrZadRkKoNvd9/kDX8=
|
github.com/emvi/pirsch v1.5.1/go.mod h1:GDijqLHM331iWtmDmc7th19RxDrZadRkKoNvd9/kDX8=
|
||||||
|
github.com/emvi/pirsch v1.5.2 h1:fKGTOngDbVFhbzhbXy2NbaeZrVYSiIoDVy+dce0agFs=
|
||||||
|
github.com/emvi/pirsch v1.5.2/go.mod h1:GDijqLHM331iWtmDmc7th19RxDrZadRkKoNvd9/kDX8=
|
||||||
|
github.com/emvi/pirsch v1.5.3-0.20200914194223-a990d20e91a2 h1:HoKxeUtA0E4QVuw2kaR4TioT2OZPIzXQ2rA6EJ3GRTM=
|
||||||
|
github.com/emvi/pirsch v1.5.3-0.20200914194223-a990d20e91a2/go.mod h1:GDijqLHM331iWtmDmc7th19RxDrZadRkKoNvd9/kDX8=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
|||||||
6
main.go
6
main.go
@@ -123,7 +123,7 @@ func serveTracking() http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
activeVisitorPages, activeVisitors := tracking.GetActiveVisitors()
|
activeVisitorPages, activeVisitors := tracking.GetActiveVisitors()
|
||||||
totalVisitorsLabels, totalVisitorsDps := tracking.GetTotalVisitors(startDate, endDate)
|
totalVisitorsLabels, totalVisitorsDps, sessionsDps, bouncesDps := tracking.GetTotalVisitors(startDate, endDate)
|
||||||
hourlyVisitorsTodayLabels, hourlyVisitorsTodayDps := tracking.GetHourlyVisitorsToday()
|
hourlyVisitorsTodayLabels, hourlyVisitorsTodayDps := tracking.GetHourlyVisitorsToday()
|
||||||
pageVisitors, pageRank := tracking.GetPageVisits(startDate, endDate)
|
pageVisitors, pageRank := tracking.GetPageVisits(startDate, endDate)
|
||||||
tplCache.RenderWithoutCache(w, "tracking.html", struct {
|
tplCache.RenderWithoutCache(w, "tracking.html", struct {
|
||||||
@@ -132,6 +132,8 @@ func serveTracking() http.HandlerFunc {
|
|||||||
EndDate time.Time
|
EndDate time.Time
|
||||||
TotalVisitorsLabels template.JS
|
TotalVisitorsLabels template.JS
|
||||||
TotalVisitorsDps template.JS
|
TotalVisitorsDps template.JS
|
||||||
|
SessionsDps template.JS
|
||||||
|
BouncesDps template.JS
|
||||||
PageVisitors []tracking.PageVisitors
|
PageVisitors []tracking.PageVisitors
|
||||||
PageRank []tracking.PageVisitors
|
PageRank []tracking.PageVisitors
|
||||||
Languages []pirsch.LanguageStats
|
Languages []pirsch.LanguageStats
|
||||||
@@ -149,6 +151,8 @@ func serveTracking() http.HandlerFunc {
|
|||||||
endDate,
|
endDate,
|
||||||
totalVisitorsLabels,
|
totalVisitorsLabels,
|
||||||
totalVisitorsDps,
|
totalVisitorsDps,
|
||||||
|
sessionsDps,
|
||||||
|
bouncesDps,
|
||||||
pageVisitors,
|
pageVisitors,
|
||||||
pageRank,
|
pageRank,
|
||||||
tracking.GetLanguages(startDate, endDate),
|
tracking.GetLanguages(startDate, endDate),
|
||||||
|
|||||||
23
schema/0002_pirsch_update.up.sql
Normal file
23
schema/0002_pirsch_update.up.sql
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
ALTER TABLE "hit" ADD COLUMN "screen_width" integer DEFAULT 0;
|
||||||
|
ALTER TABLE "hit" ADD COLUMN "screen_height" integer DEFAULT 0;
|
||||||
|
|
||||||
|
CREATE TABLE "screen_stats" (
|
||||||
|
id bigint NOT NULL UNIQUE,
|
||||||
|
tenant_id bigint,
|
||||||
|
day date NOT NULL,
|
||||||
|
visitors integer NOT NULL,
|
||||||
|
width integer NOT NULL,
|
||||||
|
height integer NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE SEQUENCE screen_stats_id_seq
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
ALTER SEQUENCE screen_stats_id_seq OWNED BY "screen_stats".id;
|
||||||
|
ALTER TABLE ONLY "screen_stats" ALTER COLUMN id SET DEFAULT nextval('screen_stats_id_seq'::regclass);
|
||||||
|
ALTER TABLE ONLY "screen_stats" ADD CONSTRAINT screen_stats_pkey PRIMARY KEY (id);
|
||||||
|
CREATE INDEX screen_stats_day_index ON screen_stats(day);
|
||||||
@@ -234,12 +234,26 @@
|
|||||||
type: "line",
|
type: "line",
|
||||||
data: {
|
data: {
|
||||||
labels: [{{.TotalVisitorsLabels}}],
|
labels: [{{.TotalVisitorsLabels}}],
|
||||||
datasets: [{
|
datasets: [
|
||||||
backgroundColor: "rgba(127, 127, 127, 0.05)",
|
{
|
||||||
borderColor: "#7f7f7f",
|
backgroundColor: "rgb(43, 180, 0, 0.02)",
|
||||||
label: "Total Visitors",
|
borderColor: "rgb(40, 152, 0, 0.5)",
|
||||||
data: [{{.TotalVisitorsDps}}]
|
label: "Total Visitors",
|
||||||
}]
|
data: [{{.TotalVisitorsDps}}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
backgroundColor: "rgb(0, 63, 197, 0.02)",
|
||||||
|
borderColor: "rgb(0, 53, 159, 0.5)",
|
||||||
|
label: "Sessions",
|
||||||
|
data: [{{.SessionsDps}}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
backgroundColor: "rgba(194, 0, 0, 0.02)",
|
||||||
|
borderColor: "rgb(152, 0, 0, 0.5)",
|
||||||
|
label: "Bounces",
|
||||||
|
data: [{{.BouncesDps}}]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -263,12 +277,26 @@
|
|||||||
type: "line",
|
type: "line",
|
||||||
data: {
|
data: {
|
||||||
labels: [{{$data.Labels}}],
|
labels: [{{$data.Labels}}],
|
||||||
datasets: [{
|
datasets: [
|
||||||
backgroundColor: "rgba(127, 127, 127, 0.05)",
|
{
|
||||||
borderColor: "#7f7f7f",
|
backgroundColor: "rgb(43, 180, 0, 0.02)",
|
||||||
label: "Page Visits",
|
borderColor: "rgb(40, 152, 0, 0.5)",
|
||||||
data: [{{$data.Data}}]
|
label: "Page Visits",
|
||||||
}]
|
data: [{{$data.Data}}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
backgroundColor: "rgb(0, 63, 197, 0.02)",
|
||||||
|
borderColor: "rgb(0, 53, 159, 0.5)",
|
||||||
|
label: "Sessions",
|
||||||
|
data: [{{$data.Sessions}}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
backgroundColor: "rgba(194, 0, 0, 0.02)",
|
||||||
|
borderColor: "rgb(152, 0, 0, 0.5)",
|
||||||
|
label: "Bounces",
|
||||||
|
data: [{{$data.Bounces}}]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ type PageVisitors struct {
|
|||||||
Visitors int
|
Visitors int
|
||||||
Labels template.JS
|
Labels template.JS
|
||||||
Data template.JS
|
Data template.JS
|
||||||
|
Sessions template.JS
|
||||||
|
Bounces template.JS
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetActiveVisitors() ([]pirsch.Stats, int) {
|
func GetActiveVisitors() ([]pirsch.Stats, int) {
|
||||||
@@ -43,12 +45,12 @@ func GetHourlyVisitorsToday() (template.JS, template.JS) {
|
|||||||
return getLabelsAndDataHourly(visitors)
|
return getLabelsAndDataHourly(visitors)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTotalVisitors(startDate, endDate time.Time) (template.JS, template.JS) {
|
func GetTotalVisitors(startDate, endDate time.Time) (template.JS, template.JS, template.JS, template.JS) {
|
||||||
visitors, err := analyzer.Visitors(&pirsch.Filter{From: startDate, To: endDate})
|
visitors, err := analyzer.Visitors(&pirsch.Filter{From: startDate, To: endDate})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logbuch.Error("Error reading visitor statistics", logbuch.Fields{"err": err})
|
logbuch.Error("Error reading visitor statistics", logbuch.Fields{"err": err})
|
||||||
return "", ""
|
return "", "", "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return getLabelsAndData(visitors)
|
return getLabelsAndData(visitors)
|
||||||
@@ -65,12 +67,14 @@ func GetPageVisits(startDate, endDate time.Time) ([]PageVisitors, []PageVisitors
|
|||||||
pageVisitors := make([]PageVisitors, len(visits))
|
pageVisitors := make([]PageVisitors, len(visits))
|
||||||
|
|
||||||
for i, visit := range visits {
|
for i, visit := range visits {
|
||||||
labels, data := getLabelsAndData(visit.Stats)
|
labels, data, sessions, bounces := getLabelsAndData(visit.Stats)
|
||||||
pageVisitors[i] = PageVisitors{
|
pageVisitors[i] = PageVisitors{
|
||||||
Path: visit.Path,
|
Path: visit.Path,
|
||||||
Visitors: sumVisitors(visit.Stats),
|
Visitors: sumVisitors(visit.Stats),
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
Data: data,
|
Data: data,
|
||||||
|
Sessions: sessions,
|
||||||
|
Bounces: bounces,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,18 +152,27 @@ func sumVisitors(stats []pirsch.Stats) int {
|
|||||||
return sum
|
return sum
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLabelsAndData(visitors []pirsch.Stats) (template.JS, template.JS) {
|
func getLabelsAndData(visitors []pirsch.Stats) (template.JS, template.JS, template.JS, template.JS) {
|
||||||
var labels strings.Builder
|
var labels strings.Builder
|
||||||
var dp strings.Builder
|
var dp strings.Builder
|
||||||
|
var sessions strings.Builder
|
||||||
|
var bounces strings.Builder
|
||||||
|
|
||||||
for _, point := range visitors {
|
for _, point := range visitors {
|
||||||
labels.WriteString(fmt.Sprintf("'%s',", point.Day.Format(statisticsDateFormat)))
|
labels.WriteString(fmt.Sprintf("'%s',", point.Day.Format(statisticsDateFormat)))
|
||||||
dp.WriteString(fmt.Sprintf("%d,", point.Visitors))
|
dp.WriteString(fmt.Sprintf("%d,", point.Visitors))
|
||||||
|
sessions.WriteString(fmt.Sprintf("%d,", point.Sessions))
|
||||||
|
bounces.WriteString(fmt.Sprintf("%d,", point.Bounces))
|
||||||
}
|
}
|
||||||
|
|
||||||
labelsStr := labels.String()
|
labelsStr := labels.String()
|
||||||
dataStr := dp.String()
|
dataStr := dp.String()
|
||||||
return template.JS(labelsStr[:len(labelsStr)-1]), template.JS(dataStr[:len(dataStr)-1])
|
sessionsStr := sessions.String()
|
||||||
|
bouncesStr := bounces.String()
|
||||||
|
return template.JS(labelsStr[:len(labelsStr)-1]),
|
||||||
|
template.JS(dataStr[:len(dataStr)-1]),
|
||||||
|
template.JS(sessionsStr[:len(sessionsStr)-1]),
|
||||||
|
template.JS(bouncesStr[:len(bouncesStr)-1])
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLabelsAndDataHourly(visitors []pirsch.VisitorTimeStats) (template.JS, template.JS) {
|
func getLabelsAndDataHourly(visitors []pirsch.VisitorTimeStats) (template.JS, template.JS) {
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ func NewTracker() (*pirsch.Tracker, context.CancelFunc) {
|
|||||||
|
|
||||||
store = pirsch.NewPostgresStore(conn, nil)
|
store = pirsch.NewPostgresStore(conn, nil)
|
||||||
tracker := pirsch.NewTracker(store, os.Getenv("MB_TRACKING_SALT"), &pirsch.TrackerConfig{
|
tracker := pirsch.NewTracker(store, os.Getenv("MB_TRACKING_SALT"), &pirsch.TrackerConfig{
|
||||||
// I don't care about traffic from my own website
|
ReferrerDomainBlacklist: []string{"marvinblum.de"}, // I don't care about traffic from my own website
|
||||||
ReferrerDomainBlacklist: []string{"marvinblum.de"},
|
|
||||||
ReferrerDomainBlacklistIncludesSubdomains: true,
|
ReferrerDomainBlacklistIncludesSubdomains: true,
|
||||||
|
Sessions: true,
|
||||||
})
|
})
|
||||||
analyzer = pirsch.NewAnalyzer(store)
|
analyzer = pirsch.NewAnalyzer(store)
|
||||||
processor := pirsch.NewProcessor(store)
|
processor := pirsch.NewProcessor(store)
|
||||||
|
|||||||
Reference in New Issue
Block a user