diff --git a/pkg/aggregator/aggregator.go b/pkg/aggregator/aggregator.go index d8fa300..fc89a6e 100644 --- a/pkg/aggregator/aggregator.go +++ b/pkg/aggregator/aggregator.go @@ -81,10 +81,12 @@ func (agg *aggregator) Process(pageviews []*models.Pageview) *results { } site.HandlePageview(p) - err = agg.handlePageview(results, p) + pageStats, err := agg.getPageStats(results, p.Timestamp, p.Hostname, p.Pathname) if err != nil { + log.Error(err) continue } + pageStats.HandlePageview(p) // referrer stats if p.Referrer != "" { diff --git a/pkg/aggregator/pageviews.go b/pkg/aggregator/pageviews.go deleted file mode 100644 index 56d7c76..0000000 --- a/pkg/aggregator/pageviews.go +++ /dev/null @@ -1,36 +0,0 @@ -package aggregator - -import ( - log "github.com/sirupsen/logrus" - "github.com/usefathom/fathom/pkg/models" -) - -func (agg *aggregator) handlePageview(results *results, p *models.Pageview) error { - pageStats, err := agg.getPageStats(results, p.Timestamp, p.Hostname, p.Pathname) - if err != nil { - log.Error(err) - return err - } - - pageStats.Pageviews += 1 - if p.IsUnique { - pageStats.Visitors += 1 - } - - if p.Duration > 0.00 { - pageStats.KnownDurations += 1 - pageStats.AvgDuration = pageStats.AvgDuration + ((float64(p.Duration) - pageStats.AvgDuration) * 1 / float64(pageStats.KnownDurations)) - } - - if p.IsNewSession { - pageStats.Entries += 1 - - if p.IsBounce { - pageStats.BounceRate = ((float64(pageStats.Entries-1) * pageStats.BounceRate) + 1.00) / (float64(pageStats.Entries)) - } else { - pageStats.BounceRate = ((float64(pageStats.Entries-1) * pageStats.BounceRate) + 0.00) / (float64(pageStats.Entries)) - } - } - - return nil -} diff --git a/pkg/models/page_stats.go b/pkg/models/page_stats.go index 48d0554..d3ec796 100644 --- a/pkg/models/page_stats.go +++ b/pkg/models/page_stats.go @@ -15,3 +15,27 @@ type PageStats struct { KnownDurations int64 `db:"known_durations"` Date time.Time `db:"date" json:",omitempty"` } + +func (s *PageStats) HandlePageview(p *Pageview) { + + s.Pageviews += 1 + if p.IsUnique { + s.Visitors += 1 + } + + if p.Duration > 0.00 { + s.KnownDurations += 1 + s.AvgDuration = s.AvgDuration + ((float64(p.Duration) - s.AvgDuration) * 1 / float64(s.KnownDurations)) + } + + if p.IsNewSession { + s.Entries += 1 + + if p.IsBounce { + s.BounceRate = ((float64(s.Entries-1) * s.BounceRate) + 1.00) / (float64(s.Entries)) + } else { + s.BounceRate = ((float64(s.Entries-1) * s.BounceRate) + 0.00) / (float64(s.Entries)) + } + } + +} diff --git a/pkg/models/page_stats_test.go b/pkg/models/page_stats_test.go new file mode 100644 index 0000000..99ac4df --- /dev/null +++ b/pkg/models/page_stats_test.go @@ -0,0 +1,67 @@ +package models + +import "testing" + +func TestPageStatsHandlePageview(t *testing.T) { + s := PageStats{} + + p1 := &Pageview{ + Duration: 100, + IsBounce: false, + IsUnique: true, + IsNewSession: true, + } + p2 := &Pageview{ + Duration: 60, + IsUnique: false, + IsNewSession: false, + IsBounce: true, // should have no effect because only new sessions can bounce + } + p3 := &Pageview{ + IsUnique: true, + IsNewSession: true, + IsBounce: true, + } + + // add first pageview & test + s.HandlePageview(p1) + if s.Pageviews != 1 { + t.Errorf("Pageviews: expected %d, got %d", 1, s.Pageviews) + } + if s.Visitors != 1 { + t.Errorf("Visitors: expected %d, got %d", 1, s.Visitors) + } + if s.AvgDuration != 100 { + t.Errorf("AvgDuration: expected %.2f, got %.2f", 100.00, s.AvgDuration) + } + if s.BounceRate != 0.00 { + t.Errorf("BounceRate: expected %.2f, got %.2f", 0.00, s.BounceRate) + } + + // add second pageview + s.HandlePageview(p2) + if s.Pageviews != 2 { + t.Errorf("Pageviews: expected %d, got %d", 2, s.Pageviews) + } + if s.Visitors != 1 { + t.Errorf("Visitors: expected %d, got %d", 1, s.Visitors) + } + if s.AvgDuration != 80 { + t.Errorf("AvgDuration: expected %.2f, got %.2f", 80.00, s.AvgDuration) + } + // should still be 0.00 because p2 was not a new session + if s.BounceRate != 0.00 { + t.Errorf("BounceRate: expected %.2f, got %.2f", 0.00, s.BounceRate) + } + + // add third pageview + s.HandlePageview(p3) + if s.Visitors != 2 { + t.Errorf("Visitors: expected %d, got %d", 2, s.Visitors) + } + + if s.BounceRate != 0.50 { + t.Errorf("BounceRate: expected %.2f, got %.2f", 0.50, s.BounceRate) + } + +}