pirsch

package module
v1.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 1, 2020 License: MIT Imports: 26 Imported by: 0

README

Pirsch

GoDoc Go Report Card CircleCI Chat on Discord

Pirsch is a server side, no-cookie, drop-in and privacy focused tracking solution for Go. Integrated into a Go application it enables you to track HTTP traffic without invading the privacy of your visitors. The visualization of the data (dashboard) is not part of this project.

The name is in German and refers to a special kind of hunt: the hunter carefully and quietly enters the area to be hunted, he stalks against the wind in order to get as close as possible to the prey without being noticed.

How does it work?

Pirsch generates a unique fingerprint for each visitor. The fingerprint is a hash of the visitors IP, User-Agent, the date, and a salt. The date guarantees that the data is separated by day, so visitors can only be tracked for up to one day.

Each time a visitor opens your page, Pirsch will store a hit. The hits are analyzed later to extract meaningful data and reduce storage usage by aggregation.

The tracking works without invading the visitor's privacy as no cookies are used nor required. Pirsch can track visitors using ad blockers that block trackers like Google Analytics.

Features

Pirsch tracks the following data:

  • visitors per day, path, and hour
  • languages
  • operating system and browser (including versions)
  • referrers
  • session count
  • bounces

All timestamps are stored as UTC. Each data point belongs to an (optional) tenant, which can be used to split data between multiple domains for example. If you just integrate Pirsch into your application, you don't need to care about that field. But if you do, you need to set a tenant ID for all columns!

Usage

To store hits and statistics, Pirsch uses a database. Right now only Postgres is supported, but new ones can easily be added by implementing the Store interface. The schema can be found within the schema directory. Changes will be added to migrations scripts, so that you can add them to your projects database migration or run them manually.

Server-side tracking

Here is a quick demo on how to use the library:

// Create a new Postgres store to save statistics and hits.
store := pirsch.NewPostgresStore(db, nil)

// Set up a default tracker with a salt.
// This will buffer and store hits and generate sessions by default.
tracker := pirsch.NewTracker(store, "salt", nil)

// Create a new process and run it each day on midnight (UTC) to process the stored hits.
// The processor also cleans up the hits.
processor := pirsch.NewProcessor(store)
pirsch.RunAtMidnight(func() {
    if err := processor.Process(); err != nil {
        panic(err)
    }
})

// Create a handler to serve traffic.
// We prevent tracking resources by checking the path. So a file on /my-file.txt won't create a new hit
// but all page calls will be tracked.
http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path == "/" {
        go tracker.Hit(r, nil)
    }

    w.Write([]byte("<h1>Hello World!</h1>"))
}))

// And finally, start the server.
// We don't flush hits on shutdown but you should add that in a real application by calling Tracker.Flush().
log.Println("Starting server on port 8080...")
http.ListenAndServe(":8080", nil)

To analyze hits and processed data you can use the analyzer, which provides convenience functions to extract useful information.

The secret salt passed to NewTracker should not be known outside your organization as it can be used to generate fingerprints equal to yours. Note that while you can generate the salt at random, the fingerprints will change too. To get reliable data configure a fixed salt and treat it like a password.

// This also needs access to the store.
// You can set a time zone through the configuration to display local times.
analyzer := pirsch.NewAnalyzer(store, nil)

// As an example, lets extract the total number of visitors.
// The filter is used to specify the time frame you're looking at (days) and is optional.
// If you pass nil, the Analyzer returns data for the past week including today.
visitors, err := analyzer.Visitors(&pirsch.Filter{
    From: yesterday(),
    To: today()
})
Client-side tracking

You can also track visitors on the client side by adding pirsch.js to your website. It will perform a GET request to the configured endpoint.

<!-- add the tracking script to the head area and configure it using attributes -->
<script type="text/javascript" src="js/pirsch.js" id="pirschjs"
        data-endpoint="/count"
        data-tenant-id="42"
        data-track-localhost
        data-param-optional-param="test"></script>

The parameters are configured through HTML attributes. All of them are optional, except for the id. Here is a list of the possible options.

Option Description Default
data-endpoint The endpoint to call. This can be a local path, like /tracking, or a complete URL, like http://mywebsite.com/tracking. It must not contain any parameters. /pirsch
data-tenant-id The tenant ID to use, in case you plan to track multiple websites using the same backend or you want to split the data. Note that the tenant ID must be validated in the backend. 0 (no tenant)
data-track-localhost Enable tracking hits on localhost. This is used for testing purposes only. false
data-param-* Additional parameters to send with the request. The name send is everything after data-param-. (no parameters)

To track the hits you need to call Hit from the endpoint that you configured for pirsch.js. Here is a simple example.

// Create an endpoint to handle client tracking requests.
// HitOptionsFromRequest is a utility function to process the required parameters.
// You might want to additional checks, like for the tenant ID.
http.Handle("/count", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    tracker.Hit(r, pirsch.HitOptionsFromRequest(r))
}))

HitOptionsFromRequest will read the parameters send by pirsch.js and returns a new HitOptions object that can be passed to Hit. You might want to split these steps into two, to run additional checks for the parameters that were send by the user.

Mapping IPs to countries

Pirsch uses MaxMind's GeoLite2 database to map IPs to countries. The database is not included, so you need to download it yourself. IP mapping is optional, it must explicitly be enabled by setting the GeoDB attribute of the TrackerConfig or through the HitOptions when calling HitFromRequest.

  1. create an account at MaxMind
  2. generate a new license key
  3. call GetGeoLite2 with the path you would like to extract the tarball to and pass your license key
  4. create a new GeoDB by using NewGeoDB and the file you downloaded and extracted using the step before

The GeoDB should be updated on a regular basis. The Tracker has a method SetGeoDB to update the GeoDB at runtime (thread-safe).

Documentation

Read the full documentation for details, check out demos, or read the article at https://marvinblum.de/blog/how-i-built-my-website-using-emvi-as-a-headless-cms-RGaqOqK18w.

Build pirsch.js

To minify pirsch.js to pirsch.min.js you need to run npm i and npm run minify inside the js directory.

Changelog

1.7.1
  • fixed filtering referrer spam subdomains
1.7.0
  • Tracker.Hit does no longer spawn its own goroutine, so you should do that yourself
  • added visitors statistics for time and day for a range of days to Analyzer
  • added optional time zone to Analyzer
  • fixed reading sessions without tenant ID
  • fixed reading hit days without time zone
1.6.0

You need to update the schema by running the v1.6.0.sql migration script!

  • added client side tracking (pirsch.js)
  • added screen size to Hit, Processor and Anlayzer for client side tracking
  • Tracker.Stop now processes all hits in queue before shutting down (Tracker.Flush does not!)
  • improved documentation and demos
  • fixed counting bounces for path
  • fixed counting platforms
1.5.2
  • fixed grouping language, referrer, OS, and browser statistics
1.5.1
  • fixed counting active visitors
  • fixed counting platforms
  • fixed reading statistics for today if no history exists
1.5.0

You need to update the schema by running the v1.5.0.sql migration script! WARNING: this release uses a new data structure to store statistics and is incompatible with previous versions. You need to migrate and drop the unused tables using the following statements (migration steps NOT included):

DROP TABLE "visitor_platform";
DROP TABLE "visitors_per_browser";
DROP TABLE "visitors_per_day";
DROP TABLE "visitors_per_hour";
DROP TABLE "visitors_per_language";
DROP TABLE "visitors_per_os";
DROP TABLE "visitors_per_page";
DROP TABLE "visitors_per_referrer";
  • implemented a new data model
  • added session tracking
  • added referrer spam protection
  • added bounce rates
  • re-implemented the Analyzer to support the new data model and make it easier to use
1.4.3

You need to update the schema by running the v1.4.3.sql migration script!

  • fixed saving processed data
1.4.2
  • fixed null fields in model
  • fixed counting visitors multiple times (by using a transaction to rollback changes in case the processor fails)
  • added optional log.Logger to Tracker and PostgresStore
  • removed all panics and log errors instead
1.4.1
  • added relative visitor statistics for OS and browser usage
1.4.0

You need to update the schema by running the v1.4.0.sql migration script!

  • added parsing the User-Agent header to extract the OS, OS version, browser, and browser version
  • added OS, browser and platform statistics to Processor and Analyzer
  • Pirsch now uses a single struct for all statistics called Stats
  • fixed error channel size in Processor
  • a few smaller refactorings
1.3.3
  • fixed extracting Referer header
  • added ref, referer and referrer query parameters for referrers, when Referer header is not present
1.3.2

You need to update the schema by running the v1.3.2.sql migration script!

  • fixed helper function RunAtMidnight not using UTC for all times
  • referer -> referrer
1.3.1
  • added statistics for visitor count per page and referrer
1.3.0

You need to update the schema by running the v1.3.0.sql migration script!

  • added cancel function to RunAtMidnight
  • added helper function for tenant IDs
  • hits for an empty User-Agent will be ignored from now on
  • added configuration options to Processor
  • IgnoreHit and HitFromRequest are now exported functions
  • added options to filter for unwanted referrer, like your own domain
  • added referrer statistics to Processor and Analyzer
  • added method to Analyzer to extract active visitor pages
  • Analyzer results are now sorted by visitors in descending order instead of path and referrer length
1.2.0

You need to update the schema by running the v1.2.0.sql migration script!

  • the processor now returns an error
  • the processor now updates existing statistics in case it has been run before, but keep in mind that it drops hits and therefor breaks tracking users that return on the same day. It's recommended to run the processor for days in the past excluding today
  • (optional) multi-tenancy support to track multiple domains using the same database. In case you don't want to use it, use null as the tenant_id
  • improved IP extraction from X-Forwarded-For, Forwarded and X-Real-IP headers
1.1.1
  • fixed error in case values are too long
  • fixed language statistics not including today
1.1.0
  • added a secret salt to prevent generating fingerprints to identify visitors on other websites (man in the middle)
  • extended bot list
1.0.0

Initial release.

Contribution

Contributions are welcome! You can extend the bot list or processor to extract more useful data, for example. Please open a pull requests for your changes and tickets in case you would like to discuss something or have a question.

To run the tests you'll need a Postgres database and a schema called pirsch. The user and password are set to postgres.

License

MIT

Documentation

Index

Constants

View Source
const (
	// BrowserChrome represents the Chrome and Chromium browser.
	BrowserChrome = "Chrome"

	// BrowserFirefox represents the Firefox browser.
	BrowserFirefox = "Firefox"

	// BrowserSafari  represents the Safari browser.
	BrowserSafari = "Safari"

	// BrowserOpera represents the Opera browser.
	BrowserOpera = "Opera"

	// BrowserEdge represents the Edge browser.
	BrowserEdge = "Edge"

	// BrowserIE represents the Internet Explorer browser.
	BrowserIE = "IE"

	// OSWindows represents the Windows operating system.
	OSWindows = "Windows"

	// OSMac represents the Mac operating system.
	OSMac = "Mac"

	// OSLinux represents a Linux distribution.
	OSLinux = "Linux"

	// OSAndroid represents the Android operating system.
	OSAndroid = "Android"

	// OSiOS represents the iOS operating system.
	OSiOS = "iOS"

	// OSWindowsMobile represents the Windows Mobile operating system.
	OSWindowsMobile = "Windows Mobile"
)
View Source
const (

	// GeoLite2Filename is the default filename of the GeoLite2 database.
	GeoLite2Filename = "GeoLite2-Country.mmdb"
)

Variables

View Source
var NullTenant = NewTenantID(0)

NullTenant can be used to pass no (null) tenant to filters and functions. This is a sql.NullInt64 with a value of 0.

Functions

func Fingerprint

func Fingerprint(r *http.Request, salt string) string

Fingerprint returns a hash for given request and salt. The hash is unique for the visitor.

func GetGeoLite2 added in v1.6.0

func GetGeoLite2(path, licenseKey string) error

GetGeoLite2 downloads and unpacks the MaxMind GeoLite2 database. The tarball is downloaded and unpacked at the provided path. The directories will created if required. The license key is used for the download and must be provided for a registered account. Please refer to MaxMinds website on how to do that: https://dev.maxmind.com/geoip/geoip2/geolite2/ The database should be updated on a regular basis.

func IgnoreHit added in v1.3.0

func IgnoreHit(r *http.Request) bool

IgnoreHit returns true, if a hit should be ignored for given request, or false otherwise. The easiest way to track visitors is to use the Tracker.

func NewTenantID added in v1.3.0

func NewTenantID(id int64) sql.NullInt64

NewTenantID is a helper function to return a sql.NullInt64. The ID is considered valid if greater than 0.

func RunAtMidnight

func RunAtMidnight(f func()) context.CancelFunc

RunAtMidnight calls given function on each day of month on midnight (UTC), unless it is cancelled by calling the cancel function.

Types

type Analyzer

type Analyzer struct {
	// contains filtered or unexported fields
}

Analyzer provides an interface to analyze processed data and hits.

func NewAnalyzer

func NewAnalyzer(store Store, config *AnalyzerConfig) *Analyzer

NewAnalyzer returns a new Analyzer for given Store.

func (*Analyzer) ActiveVisitors

func (analyzer *Analyzer) ActiveVisitors(filter *Filter, duration time.Duration) ([]Stats, int, error)

ActiveVisitors returns the active visitors per path and the total number of active visitors for given duration. Use time.Minute*5 for example to see the active visitors for the past 5 minutes. The correct date/time is not included.

func (*Analyzer) Browser added in v1.4.0

func (analyzer *Analyzer) Browser(filter *Filter) ([]BrowserStats, error)

Browser returns the visitor count per browser.

func (*Analyzer) Country added in v1.6.0

func (analyzer *Analyzer) Country(filter *Filter) ([]CountryStats, error)

Country returns the visitor count per country.

func (*Analyzer) Languages

func (analyzer *Analyzer) Languages(filter *Filter) ([]LanguageStats, error)

Languages returns the visitor count per language.

func (*Analyzer) OS added in v1.4.0

func (analyzer *Analyzer) OS(filter *Filter) ([]OSStats, error)

OS returns the visitor count per operating system.

func (*Analyzer) PageBrowser added in v1.5.0

func (analyzer *Analyzer) PageBrowser(filter *Filter) ([]BrowserStats, error)

PageBrowser returns the visitor count per brower, day, path, and for the given time frame. The path is mandatory.

func (*Analyzer) PageLanguages added in v1.5.0

func (analyzer *Analyzer) PageLanguages(filter *Filter) ([]LanguageStats, error)

PageLanguages returns the visitor count per language, day, path, and for the given time frame. The path is mandatory.

func (*Analyzer) PageOS added in v1.5.0

func (analyzer *Analyzer) PageOS(filter *Filter) ([]OSStats, error)

PageOS returns the visitor count per operating system, day, path, and for the given time frame. The path is mandatory.

func (*Analyzer) PagePlatform added in v1.5.0

func (analyzer *Analyzer) PagePlatform(filter *Filter) *VisitorStats

PagePlatform returns the visitor count per platform, day, path, and for the given time frame. The path is mandatory.

func (*Analyzer) PageReferrer added in v1.5.0

func (analyzer *Analyzer) PageReferrer(filter *Filter) ([]ReferrerStats, error)

PageReferrer returns the visitor count per referrer, day, path, and for the given time frame. The path is mandatory.

func (*Analyzer) PageVisitors added in v1.5.0

func (analyzer *Analyzer) PageVisitors(filter *Filter) ([]PathVisitors, error)

PageVisitors returns the visitor count, session count, and bounce rate per day for the given time frame grouped by path.

func (*Analyzer) Platform added in v1.4.0

func (analyzer *Analyzer) Platform(filter *Filter) *VisitorStats

Platform returns the visitor count per browser.

func (*Analyzer) Referrer added in v1.3.2

func (analyzer *Analyzer) Referrer(filter *Filter) ([]ReferrerStats, error)

Referrer returns the visitor count per referrer.

func (*Analyzer) Screen added in v1.6.0

func (analyzer *Analyzer) Screen(filter *Filter) ([]ScreenStats, error)

Screen returns the visitor count per screen size (width and height).

func (*Analyzer) TimeOfDay added in v1.7.0

func (analyzer *Analyzer) TimeOfDay(filter *Filter) ([]TimeOfDayVisitors, error)

TimeOfDay returns the visitor count per day and hour for given time frame.

func (*Analyzer) VisitorHours added in v1.5.0

func (analyzer *Analyzer) VisitorHours(filter *Filter) ([]VisitorTimeStats, error)

VisitorHours returns the visitor and session count grouped by hour of day for given time frame.

func (*Analyzer) Visitors

func (analyzer *Analyzer) Visitors(filter *Filter) ([]Stats, error)

Visitors returns the visitor count, session count, and bounce rate per day.

type AnalyzerConfig added in v1.7.0

type AnalyzerConfig struct {
	// Timezone sets the time zone for the result set.
	// If not set, UTC will be used.
	Timezone *time.Location
}

AnalyzerConfig is the (optional) configuration for the Analyzer.

type BaseEntity added in v1.4.0

type BaseEntity struct {
	ID       int64         `db:"id" json:"id"`
	TenantID sql.NullInt64 `db:"tenant_id" json:"tenant_id"`
}

BaseEntity is the base entity for all other entities.

type BrowserStats added in v1.5.0

type BrowserStats struct {
	Stats

	Browser        sql.NullString `db:"browser" json:"browser"`
	BrowserVersion sql.NullString `db:"browser_version" json:"version"`
}

BrowserStats is the visitor count for each path on each day and browser.

type CountryStats added in v1.6.0

type CountryStats struct {
	Stats

	CountryCode sql.NullString `db:"country_code" json:"country_code"`
}

CountryStats is the visitor count for each country on each day.

type Filter

type Filter struct {
	// TenantID is the optional tenant ID used to filter results.
	TenantID sql.NullInt64

	// Path is the optional path for the selection.
	Path string

	// From is the start of the selection.
	From time.Time

	// To is the end of the selection.
	To time.Time
}

Filter is used to specify the time frame, path and tenant for the Analyzer.

func NewFilter added in v1.4.0

func NewFilter(tenantID sql.NullInt64) *Filter

NewFilter returns a new default filter for given tenant and the past week.

func (*Filter) Days

func (filter *Filter) Days() int

Days returns the number of days covered by the filter.

type GeoDB added in v1.6.0

type GeoDB struct {
	// contains filtered or unexported fields
}

GeoDB maps IPs to their geo location based on MaxMinds GeoLite2 or GeoIP2 database.

func NewGeoDB added in v1.6.0

func NewGeoDB(file string) (*GeoDB, error)

NewGeoDB creates a new GeoDB for given database file. Make sure you call GeoDB.Close to release the system resources! If you use this in combination with GetGeoLite2, you should pass in the path to GeoLite2Filename (including the filename). The database should be updated on a regular basis.

func (*GeoDB) Close added in v1.6.0

func (db *GeoDB) Close() error

Close closes the database file handle and frees the system resources. It's important to call this when you don't need the GeoDB anymore!

func (*GeoDB) CountryCode added in v1.6.0

func (db *GeoDB) CountryCode(ip string) string

CountryCode looks up the country code for given IP. If the IP is invalid it will return an empty string. The country code is returned in lowercase.

type Hit

type Hit struct {
	BaseEntity

	Fingerprint    string         `db:"fingerprint" json:"fingerprint"`
	Session        sql.NullTime   `db:"session" json:"session"`
	Path           sql.NullString `db:"path" json:"path,omitempty"`
	URL            sql.NullString `db:"url" json:"url,omitempty"`
	Language       sql.NullString `db:"language" json:"language,omitempty"`
	UserAgent      sql.NullString `db:"user_agent" json:"user_agent,omitempty"`
	Referrer       sql.NullString `db:"referrer" json:"referrer,omitempty"`
	OS             sql.NullString `db:"os" json:"os,omitempty"`
	OSVersion      sql.NullString `db:"os_version" json:"os_version,omitempty"`
	Browser        sql.NullString `db:"browser" json:"browser,omitempty"`
	BrowserVersion sql.NullString `db:"browser_version" json:"browser_version,omitempty"`
	CountryCode    sql.NullString `db:"country_code" json:"country_code"`
	Desktop        bool           `db:"desktop" json:"desktop"`
	Mobile         bool           `db:"mobile" json:"mobile"`
	ScreenWidth    int            `db:"screen_width" json:"screen_width"`
	ScreenHeight   int            `db:"screen_height" json:"screen_height"`
	Time           time.Time      `db:"time" json:"time"`
}

Hit represents a single data point/page visit and is the central entity of pirsch.

func HitFromRequest added in v1.3.0

func HitFromRequest(r *http.Request, salt string, options *HitOptions) Hit

HitFromRequest returns a new Hit for given request, salt and HitOptions. The salt must stay consistent to track visitors across multiple calls. The easiest way to track visitors is to use the Tracker.

func (Hit) String

func (hit Hit) String() string

String implements the Stringer interface.

type HitOptions added in v1.2.0

type HitOptions struct {
	// TenantID is optionally saved with a hit to split the data between multiple tenants.
	TenantID sql.NullInt64

	// URL can be set to manually overwrite the URL stored for this request.
	// This will also affect the Path, except it is set too.
	URL string

	// Path can be set to manually overwrite the path stored for the request.
	// This will also affect the URL.
	Path string

	// Referrer can be set to manually overwrite the referrer from the request.
	Referrer string

	// ReferrerDomainBlacklist is used to filter out unwanted referrer from the Referrer header.
	// This can be used to filter out traffic from your own site or subdomains.
	// To filter your own domain and subdomains, add your domain to the list and set ReferrerDomainBlacklistIncludesSubdomains to true.
	// This way the referrer for blog.mypage.com -> mypage.com won't be saved.
	ReferrerDomainBlacklist []string

	// ReferrerDomainBlacklistIncludesSubdomains set to true to include all subdomains in the ReferrerDomainBlacklist,
	// or else subdomains must explicitly be included in the blacklist.
	// If the blacklist contains domain.com, sub.domain.com and domain.com will be treated as equally.
	ReferrerDomainBlacklistIncludesSubdomains bool

	// ScreenWidth sets the screen width to be stored with the hit.
	ScreenWidth int

	// ScreenHeight sets the screen height to be stored with the hit.
	ScreenHeight int
	// contains filtered or unexported fields
}

HitOptions is used to manipulate the data saved on a hit.

func HitOptionsFromRequest added in v1.6.0

func HitOptionsFromRequest(r *http.Request) *HitOptions

HitOptionsFromRequest returns the HitOptions for given client request. This function can be used to accept hits from pirsch.js. Invalid parameters are ignored and left empty. You might want to add additional checks before calling HitFromRequest afterwards (like for the HitOptions.TenantID).

type LanguageStats added in v1.5.0

type LanguageStats struct {
	Stats

	Language sql.NullString `db:"language" json:"language"`
}

LanguageStats is the visitor count for each path on each day and language.

type OSStats added in v1.5.0

type OSStats struct {
	Stats

	OS        sql.NullString `db:"os" json:"os"`
	OSVersion sql.NullString `db:"os_version" json:"version"`
}

OSStats is the visitor count for each path on each day and operating system.

type PathVisitors added in v1.5.0

type PathVisitors struct {
	Path  string
	Stats []Stats
}

PathVisitors represents visitor statistics per day for a path.

type PostgresConfig added in v1.4.2

type PostgresConfig struct {
	// Logger is the log.Logger used for logging.
	// The default log will be used printing to os.Stdout with "pirsch" in its prefix in case it is not set.
	Logger *log.Logger
}

PostgresConfig is the optional configuration for the PostgresStore.

type PostgresStore

type PostgresStore struct {
	DB *sqlx.DB
	// contains filtered or unexported fields
}

PostgresStore implements the Store interface.

func NewPostgresStore

func NewPostgresStore(db *sql.DB, config *PostgresConfig) *PostgresStore

NewPostgresStore creates a new postgres storage for given database connection and logger.

func (*PostgresStore) ActivePageVisitors added in v1.5.1

func (store *PostgresStore) ActivePageVisitors(tenantID sql.NullInt64, from time.Time) ([]Stats, error)

ActivePageVisitors implements the Store interface.

func (*PostgresStore) ActiveVisitors

func (store *PostgresStore) ActiveVisitors(tenantID sql.NullInt64, from time.Time) int

ActiveVisitors implements the Store interface.

func (*PostgresStore) Commit added in v1.4.2

func (store *PostgresStore) Commit(tx *sqlx.Tx)

Commit implements the Store interface.

func (*PostgresStore) CountVisitors added in v1.5.0

func (store *PostgresStore) CountVisitors(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time) *Stats

CountVisitors implements the Store interface.

func (*PostgresStore) CountVisitorsByBrowser added in v1.5.0

func (store *PostgresStore) CountVisitorsByBrowser(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time) ([]BrowserStats, error)

CountVisitorsByBrowser implements the Store interface.

func (*PostgresStore) CountVisitorsByCountryCode added in v1.6.0

func (store *PostgresStore) CountVisitorsByCountryCode(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time) ([]CountryStats, error)

CountVisitorsByCountryCode implements the Store interface.

func (*PostgresStore) CountVisitorsByLanguage added in v1.5.0

func (store *PostgresStore) CountVisitorsByLanguage(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time) ([]LanguageStats, error)

CountVisitorsByLanguage implements the Store interface.

func (*PostgresStore) CountVisitorsByOS added in v1.5.0

func (store *PostgresStore) CountVisitorsByOS(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time) ([]OSStats, error)

CountVisitorsByOS implements the Store interface.

func (*PostgresStore) CountVisitorsByPath added in v1.5.0

func (store *PostgresStore) CountVisitorsByPath(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time, path string, includePlatform bool) ([]VisitorStats, error)

CountVisitorsByPath implements the Store interface.

func (*PostgresStore) CountVisitorsByPathAndBrowser added in v1.5.0

func (store *PostgresStore) CountVisitorsByPathAndBrowser(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time, path string) ([]BrowserStats, error)

CountVisitorsByPathAndBrowser implements the Store interface.

func (*PostgresStore) CountVisitorsByPathAndHour added in v1.5.0

func (store *PostgresStore) CountVisitorsByPathAndHour(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time, path string) ([]VisitorTimeStats, error)

CountVisitorsByPathAndHour implements the Store interface.

func (*PostgresStore) CountVisitorsByPathAndLanguage added in v1.5.0

func (store *PostgresStore) CountVisitorsByPathAndLanguage(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time, path string) ([]LanguageStats, error)

CountVisitorsByPathAndLanguage implements the Store interface.

func (*PostgresStore) CountVisitorsByPathAndMaxOneHit added in v1.5.0

func (store *PostgresStore) CountVisitorsByPathAndMaxOneHit(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time, path string) int

CountVisitorsByPathAndMaxOneHit implements the Store interface.

func (*PostgresStore) CountVisitorsByPathAndOS added in v1.5.0

func (store *PostgresStore) CountVisitorsByPathAndOS(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time, path string) ([]OSStats, error)

CountVisitorsByPathAndOS implements the Store interface.

func (*PostgresStore) CountVisitorsByPathAndReferrer added in v1.5.0

func (store *PostgresStore) CountVisitorsByPathAndReferrer(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time, path string) ([]ReferrerStats, error)

CountVisitorsByPathAndReferrer implements the Store interface.

func (*PostgresStore) CountVisitorsByPlatform added in v1.5.0

func (store *PostgresStore) CountVisitorsByPlatform(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time) *VisitorStats

CountVisitorsByPlatform implements the Store interface.

func (*PostgresStore) CountVisitorsByReferrer added in v1.5.0

func (store *PostgresStore) CountVisitorsByReferrer(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time) ([]ReferrerStats, error)

CountVisitorsByReferrer implements the Store interface.

func (*PostgresStore) CountVisitorsByScreenSize added in v1.6.0

func (store *PostgresStore) CountVisitorsByScreenSize(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time) ([]ScreenStats, error)

CountVisitorsByScreenSize implements the Store interface.

func (*PostgresStore) DeleteHitsByDay

func (store *PostgresStore) DeleteHitsByDay(tx *sqlx.Tx, tenantID sql.NullInt64, day time.Time) error

DeleteHitsByDay implements the Store interface.

func (*PostgresStore) HitDays added in v1.5.0

func (store *PostgresStore) HitDays(tenantID sql.NullInt64) ([]time.Time, error)

HitDays implements the Store interface.

func (*PostgresStore) HitPaths added in v1.5.0

func (store *PostgresStore) HitPaths(tenantID sql.NullInt64, day time.Time) ([]string, error)

HitPaths implements the Store interface.

func (*PostgresStore) NewTx added in v1.4.2

func (store *PostgresStore) NewTx() *sqlx.Tx

NewTx implements the Store interface.

func (*PostgresStore) PageBrowser added in v1.5.0

func (store *PostgresStore) PageBrowser(tenantID sql.NullInt64, path string, from time.Time, to time.Time) ([]BrowserStats, error)

PageBrowser implements the Store interface.

func (*PostgresStore) PageLanguages added in v1.5.0

func (store *PostgresStore) PageLanguages(tenantID sql.NullInt64, path string, from time.Time, to time.Time) ([]LanguageStats, error)

PageLanguages implements the Store interface.

func (*PostgresStore) PageOS added in v1.5.0

func (store *PostgresStore) PageOS(tenantID sql.NullInt64, path string, from time.Time, to time.Time) ([]OSStats, error)

PageOS implements the Store interface.

func (*PostgresStore) PagePlatform added in v1.5.0

func (store *PostgresStore) PagePlatform(tenantID sql.NullInt64, path string, from time.Time, to time.Time) *VisitorStats

PagePlatform implements the Store interface.

func (*PostgresStore) PageReferrer added in v1.5.0

func (store *PostgresStore) PageReferrer(tenantID sql.NullInt64, path string, from time.Time, to time.Time) ([]ReferrerStats, error)

PageReferrer implements the Store interface.

func (*PostgresStore) PageVisitors added in v1.5.0

func (store *PostgresStore) PageVisitors(tenantID sql.NullInt64, path string, from, to time.Time) ([]Stats, error)

PageVisitors implements the Store interface.

func (*PostgresStore) Paths

func (store *PostgresStore) Paths(tenantID sql.NullInt64, from, to time.Time) ([]string, error)

Paths implements the Store interface.

func (*PostgresStore) Rollback added in v1.4.2

func (store *PostgresStore) Rollback(tx *sqlx.Tx)

Rollback implements the Store interface.

func (*PostgresStore) SaveBrowserStats added in v1.5.0

func (store *PostgresStore) SaveBrowserStats(tx *sqlx.Tx, entity *BrowserStats) error

SaveBrowserStats implements the Store interface.

func (*PostgresStore) SaveCountryStats added in v1.6.0

func (store *PostgresStore) SaveCountryStats(tx *sqlx.Tx, entity *CountryStats) error

SaveCountryStats implements the Store interface.

func (*PostgresStore) SaveHits added in v1.5.0

func (store *PostgresStore) SaveHits(hits []Hit) error

SaveHits implements the Store interface.

func (*PostgresStore) SaveLanguageStats added in v1.5.0

func (store *PostgresStore) SaveLanguageStats(tx *sqlx.Tx, entity *LanguageStats) error

SaveLanguageStats implements the Store interface.

func (*PostgresStore) SaveOSStats added in v1.5.0

func (store *PostgresStore) SaveOSStats(tx *sqlx.Tx, entity *OSStats) error

SaveOSStats implements the Store interface.

func (*PostgresStore) SaveReferrerStats added in v1.5.0

func (store *PostgresStore) SaveReferrerStats(tx *sqlx.Tx, entity *ReferrerStats) error

SaveReferrerStats implements the Store interface.

func (*PostgresStore) SaveScreenStats added in v1.6.0

func (store *PostgresStore) SaveScreenStats(tx *sqlx.Tx, entity *ScreenStats) error

SaveScreenStats implements the Store interface.

func (*PostgresStore) SaveVisitorStats added in v1.5.0

func (store *PostgresStore) SaveVisitorStats(tx *sqlx.Tx, entity *VisitorStats) error

SaveVisitorStats implements the Store interface.

func (*PostgresStore) SaveVisitorTimeStats added in v1.5.0

func (store *PostgresStore) SaveVisitorTimeStats(tx *sqlx.Tx, entity *VisitorTimeStats) error

SaveVisitorTimeStats implements the Store interface.

func (*PostgresStore) Session added in v1.5.0

func (store *PostgresStore) Session(tenantID sql.NullInt64, fingerprint string, maxAge time.Time) time.Time

Session implements the Store interface.

func (*PostgresStore) VisitorBrowser added in v1.4.0

func (store *PostgresStore) VisitorBrowser(tenantID sql.NullInt64, from, to time.Time) ([]BrowserStats, error)

VisitorBrowser implements the Store interface.

func (*PostgresStore) VisitorCountry added in v1.6.0

func (store *PostgresStore) VisitorCountry(tenantID sql.NullInt64, from, to time.Time) ([]CountryStats, error)

VisitorCountry implements the Store interface.

func (*PostgresStore) VisitorHours added in v1.5.0

func (store *PostgresStore) VisitorHours(tenantID sql.NullInt64, from time.Time, to time.Time) ([]VisitorTimeStats, error)

VisitorHours implements the Store interface.

func (*PostgresStore) VisitorLanguages

func (store *PostgresStore) VisitorLanguages(tenantID sql.NullInt64, from, to time.Time) ([]LanguageStats, error)

VisitorLanguages implements the Store interface.

func (*PostgresStore) VisitorOS added in v1.4.0

func (store *PostgresStore) VisitorOS(tenantID sql.NullInt64, from, to time.Time) ([]OSStats, error)

VisitorOS implements the Store interface.

func (*PostgresStore) VisitorPlatform added in v1.4.0

func (store *PostgresStore) VisitorPlatform(tenantID sql.NullInt64, from, to time.Time) *VisitorStats

VisitorPlatform implements the Store interface.

func (*PostgresStore) VisitorReferrer added in v1.3.2

func (store *PostgresStore) VisitorReferrer(tenantID sql.NullInt64, from, to time.Time) ([]ReferrerStats, error)

VisitorReferrer implements the Store interface.

func (*PostgresStore) VisitorScreenSize added in v1.6.0

func (store *PostgresStore) VisitorScreenSize(tenantID sql.NullInt64, from, to time.Time) ([]ScreenStats, error)

VisitorScreenSize implements the Store interface.

func (*PostgresStore) Visitors

func (store *PostgresStore) Visitors(tenantID sql.NullInt64, from, to time.Time) ([]Stats, error)

Visitors implements the Store interface.

type Processor

type Processor struct {
	// contains filtered or unexported fields
}

Processor processes hits to reduce them into meaningful statistics.

func NewProcessor

func NewProcessor(store Store) *Processor

NewProcessor creates a new Processor for given Store.

func (*Processor) Process

func (processor *Processor) Process() error

Process processes all hits in database and deletes them afterwards.

func (*Processor) ProcessTenant added in v1.2.0

func (processor *Processor) ProcessTenant(tenantID sql.NullInt64) error

ProcessTenant processes all hits in database for given tenant and deletes them afterwards. The tenant can be set to nil if you don't split your data (which is usually the case).

type ReferrerStats added in v1.5.0

type ReferrerStats struct {
	Stats

	Referrer sql.NullString `db:"referrer" json:"referrer"`
}

ReferrerStats is the visitor count for each path on each day and referrer.

type ScreenStats added in v1.6.0

type ScreenStats struct {
	Stats

	Width  int `db:"width" json:"width"`
	Height int `db:"height" json:"height"`
}

ScreenStats is the visitor count for each screen resolution on each day.

type Stats added in v1.4.0

type Stats struct {
	BaseEntity

	Day              time.Time `db:"day" json:"day"`
	Path             string    `db:"path" json:"path"`
	Visitors         int       `db:"visitors" json:"visitors"`
	Sessions         int       `db:"sessions" json:"sessions"`
	Bounces          int       `db:"bounces" json:"bounces"`
	RelativeVisitors float64   `db:"-" json:"relative_visitors"`
	BounceRate       float64   `db:"-" json:"bounce_rate"`
}

Stats is the base entity for all statistics.

func (*Stats) GetID added in v1.5.0

func (stats *Stats) GetID() int64

GetID returns the ID.

func (*Stats) GetVisitors added in v1.5.0

func (stats *Stats) GetVisitors() int

GetVisitors returns the visitor count.

type Store

type Store interface {
	// NewTx creates a new transaction and panic on failure.
	NewTx() *sqlx.Tx

	// Commit commits given transaction and logs the error.
	Commit(*sqlx.Tx)

	// Rollback rolls back given transaction and logs the error.
	Rollback(*sqlx.Tx)

	// SaveHits persists a list of hits.
	SaveHits([]Hit) error

	// DeleteHitsByDay deletes all hits on given day.
	DeleteHitsByDay(*sqlx.Tx, sql.NullInt64, time.Time) error

	// SaveVisitorStats saves VisitorStats.
	SaveVisitorStats(*sqlx.Tx, *VisitorStats) error

	// SaveVisitorTimeStats saves VisitorTimeStats.
	SaveVisitorTimeStats(*sqlx.Tx, *VisitorTimeStats) error

	// SaveLanguageStats saves LanguageStats.
	SaveLanguageStats(*sqlx.Tx, *LanguageStats) error

	// SaveReferrerStats saves ReferrerStats.
	SaveReferrerStats(*sqlx.Tx, *ReferrerStats) error

	// SaveOSStats saves OSStats.
	SaveOSStats(*sqlx.Tx, *OSStats) error

	// SaveBrowserStats saves BrowserStats.
	SaveBrowserStats(*sqlx.Tx, *BrowserStats) error

	// SaveScreenStats saves ScreenStats.
	SaveScreenStats(*sqlx.Tx, *ScreenStats) error

	// SaveCountryStats saves CountryStats.
	SaveCountryStats(*sqlx.Tx, *CountryStats) error

	// Session returns the hits session timestamp for given fingerprint and max age.
	Session(sql.NullInt64, string, time.Time) time.Time

	// HitDays returns the distinct days with at least one hit.
	HitDays(sql.NullInt64) ([]time.Time, error)

	// HitPaths returns the distinct paths for given day.
	HitPaths(sql.NullInt64, time.Time) ([]string, error)

	// Paths returns the distinct paths for given time frame.
	Paths(sql.NullInt64, time.Time, time.Time) ([]string, error)

	// CountVisitors returns the visitor count for given day.
	CountVisitors(*sqlx.Tx, sql.NullInt64, time.Time) *Stats

	// CountVisitorsByPath returns the visitor count for given day, path, and if the platform should be included or not.
	CountVisitorsByPath(*sqlx.Tx, sql.NullInt64, time.Time, string, bool) ([]VisitorStats, error)

	// CountVisitorsByPathAndHour returns the visitor count for given day and path grouped by hour of day.
	CountVisitorsByPathAndHour(*sqlx.Tx, sql.NullInt64, time.Time, string) ([]VisitorTimeStats, error)

	// CountVisitorsByPathAndLanguage returns the visitor count for given day and path grouped by language.
	CountVisitorsByPathAndLanguage(*sqlx.Tx, sql.NullInt64, time.Time, string) ([]LanguageStats, error)

	// CountVisitorsByPathAndReferrer returns the visitor count for given day and path grouped by referrer.
	CountVisitorsByPathAndReferrer(*sqlx.Tx, sql.NullInt64, time.Time, string) ([]ReferrerStats, error)

	// CountVisitorsByPathAndOS returns the visitor count for given day and path grouped by operating system and operating system version.
	CountVisitorsByPathAndOS(*sqlx.Tx, sql.NullInt64, time.Time, string) ([]OSStats, error)

	// CountVisitorsByPathAndBrowser returns the visitor count for given day and path grouped by browser and browser version.
	CountVisitorsByPathAndBrowser(*sqlx.Tx, sql.NullInt64, time.Time, string) ([]BrowserStats, error)

	// CountVisitorsByLanguage returns the visitor count for given day grouped by language.
	CountVisitorsByLanguage(*sqlx.Tx, sql.NullInt64, time.Time) ([]LanguageStats, error)

	// CountVisitorsByReferrer returns the visitor count for given day grouped by referrer.
	CountVisitorsByReferrer(*sqlx.Tx, sql.NullInt64, time.Time) ([]ReferrerStats, error)

	// CountVisitorsByOS returns the visitor count for given day grouped by operating system.
	CountVisitorsByOS(*sqlx.Tx, sql.NullInt64, time.Time) ([]OSStats, error)

	// CountVisitorsByBrowser returns the visitor count for given day grouped by browser.
	CountVisitorsByBrowser(*sqlx.Tx, sql.NullInt64, time.Time) ([]BrowserStats, error)

	// CountVisitorsByScreenSize returns the visitor count for given day grouped by screen size (width and height).
	CountVisitorsByScreenSize(*sqlx.Tx, sql.NullInt64, time.Time) ([]ScreenStats, error)

	// CountVisitorsByCountryCode returns the visitor count for given day grouped by country code.
	CountVisitorsByCountryCode(*sqlx.Tx, sql.NullInt64, time.Time) ([]CountryStats, error)

	// CountVisitorsByPlatform returns the visitor count for given day grouped by platform.
	CountVisitorsByPlatform(*sqlx.Tx, sql.NullInt64, time.Time) *VisitorStats

	// CountVisitorsByPathAndMaxOneHit returns the visitor count for given day and optional path with a maximum of one hit.
	// This returns the absolut number of hits without further page calls and is used to calculate the bounce rate.
	CountVisitorsByPathAndMaxOneHit(*sqlx.Tx, sql.NullInt64, time.Time, string) int

	// ActiveVisitors returns the active visitor count for given duration.
	ActiveVisitors(sql.NullInt64, time.Time) int

	// ActivePageVisitors returns the active visitors grouped by path for given duration.
	ActivePageVisitors(sql.NullInt64, time.Time) ([]Stats, error)

	// Visitors returns the visitors for given time frame grouped by days.
	Visitors(sql.NullInt64, time.Time, time.Time) ([]Stats, error)

	// VisitorHours returns the visitors for given time frame grouped by hour of day.
	VisitorHours(sql.NullInt64, time.Time, time.Time) ([]VisitorTimeStats, error)

	// VisitorLanguages returns the visitors for given time frame grouped by language.
	VisitorLanguages(sql.NullInt64, time.Time, time.Time) ([]LanguageStats, error)

	// VisitorReferrer returns the visitor count for given time frame grouped by referrer.
	VisitorReferrer(sql.NullInt64, time.Time, time.Time) ([]ReferrerStats, error)

	// VisitorOS returns the visitor count for given time frame grouped by operating system.
	VisitorOS(sql.NullInt64, time.Time, time.Time) ([]OSStats, error)

	// VisitorBrowser returns the visitor count for given time frame grouped by browser.
	VisitorBrowser(sql.NullInt64, time.Time, time.Time) ([]BrowserStats, error)

	// VisitorPlatform returns the visitor count for given time frame grouped by platform.
	VisitorPlatform(sql.NullInt64, time.Time, time.Time) *VisitorStats

	// VisitorScreenSize returns the visitor count for given time frame grouped by screen size (width and height).
	VisitorScreenSize(sql.NullInt64, time.Time, time.Time) ([]ScreenStats, error)

	// VisitorCountry returns the visitor count for given time frame grouped by country code.
	VisitorCountry(sql.NullInt64, time.Time, time.Time) ([]CountryStats, error)

	// PageVisitors returns the visitors for given path and time frame grouped by days.
	PageVisitors(sql.NullInt64, string, time.Time, time.Time) ([]Stats, error)

	// PageReferrer returns the visitors for given path and time frame grouped by referrer.
	PageReferrer(sql.NullInt64, string, time.Time, time.Time) ([]ReferrerStats, error)

	// PageLanguages returns the visitors for given path and time frame grouped by language.
	PageLanguages(sql.NullInt64, string, time.Time, time.Time) ([]LanguageStats, error)

	// PageOS returns the visitors for given path and time frame grouped by operating system.
	PageOS(sql.NullInt64, string, time.Time, time.Time) ([]OSStats, error)

	// PageBrowser returns the visitors for given path and time frame grouped by browser.
	PageBrowser(sql.NullInt64, string, time.Time, time.Time) ([]BrowserStats, error)

	// PagePlatform returns the visitors for given path and time frame grouped by platform.
	PagePlatform(sql.NullInt64, string, time.Time, time.Time) *VisitorStats
}

Store defines an interface to persists hits and other data. The first parameter (if required) is always the tenant ID and can be left out (pirsch.NullTenant), if you don't want to split your data. This is usually the case if you integrate Pirsch into your application.

type TimeOfDayVisitors added in v1.7.0

type TimeOfDayVisitors struct {
	Day   time.Time
	Stats []VisitorTimeStats
}

TimeOfDayVisitors represents the visitor count per day and hour for a path.

type Tracker

type Tracker struct {
	// contains filtered or unexported fields
}

Tracker is the main component of Pirsch. It provides methods to track requests and store them in a data store. Make sure you call Stop to make sure the hits get stored before shutting down the server.

func NewTracker

func NewTracker(store Store, salt string, config *TrackerConfig) *Tracker

NewTracker creates a new tracker for given store, salt and config. Pass nil for the config to use the defaults. The salt is mandatory.

func (*Tracker) Flush

func (tracker *Tracker) Flush()

Flush flushes all hits to store that are currently buffered by the workers. Call Tracker.Stop to also save hits that are in the queue.

func (*Tracker) Hit

func (tracker *Tracker) Hit(r *http.Request, options *HitOptions)

Hit stores the given request. The request might be ignored if it meets certain conditions. The HitOptions, if passed, will overwrite the Tracker configuration. It's save (and recommended!) to call this function in its own goroutine.

func (*Tracker) SetGeoDB added in v1.6.0

func (tracker *Tracker) SetGeoDB(geoDB *GeoDB)

SetGeoDB sets the GeoDB for the Tracker. The call to this function is thread safe to enable life updates of the database.

func (*Tracker) Stop

func (tracker *Tracker) Stop()

Stop flushes and stops all workers.

type TrackerConfig

type TrackerConfig struct {
	// Worker sets the number of workers that are used to store hits.
	// Must be greater or equal to 1.
	Worker int

	// WorkerBufferSize is the size of the buffer used to store hits.
	// Must be greater than 0. The hits are stored in batch when the buffer is full.
	WorkerBufferSize int

	// WorkerTimeout sets the timeout used to store hits.
	// This is used to allow the workers to store hits even if the buffer is not full yet.
	// It's recommended to set this to a few seconds.
	// If you leave it 0, the default timeout is used, else it is limted to 60 seconds.
	WorkerTimeout time.Duration

	// ReferrerDomainBlacklist see HitOptions.ReferrerDomainBlacklist.
	ReferrerDomainBlacklist []string

	// ReferrerDomainBlacklistIncludesSubdomains see HitOptions.ReferrerDomainBlacklistIncludesSubdomains.
	ReferrerDomainBlacklistIncludesSubdomains bool

	// Sessions enables/disables session tracking.
	// It's enabled by default.
	Sessions bool

	// SessionMaxAge is used to define how long a session runs at maximum.
	// Set to two hours by default.
	SessionMaxAge time.Duration

	// SessionCleanupInterval sets the session cache lifetime.
	// If not passed, the default will be used.
	SessionCleanupInterval time.Duration

	// GeoDB enables/disabled mapping IPs to country codes.
	// Can be set/updated at runtime by calling Tracker.SetGeoDB.
	GeoDB *GeoDB

	// Logger is the log.Logger used for logging.
	// The default log will be used printing to os.Stdout with "pirsch" in its prefix in case it is not set.
	Logger *log.Logger
}

TrackerConfig is the optional configuration for the Tracker.

type UserAgent added in v1.4.0

type UserAgent struct {
	// Browser is the browser name.
	Browser string

	// BrowserVersion is the browser (non technical) version number.
	BrowserVersion string

	// OS is the operating system.
	OS string

	// OSVersion is the operating system version number.
	OSVersion string
}

UserAgent contains information extracted from the User-Agent header.

func ParseUserAgent added in v1.4.0

func ParseUserAgent(ua string) UserAgent

ParseUserAgent parses given User-Agent header and returns the extracted information. This just supports major browsers and operating systems, we don't care about browsers and OSes that have no market share, unless you prove us wrong.

func (*UserAgent) IsDesktop added in v1.4.0

func (ua *UserAgent) IsDesktop() bool

IsDesktop returns true if the user agent is a desktop device.

func (*UserAgent) IsMobile added in v1.4.0

func (ua *UserAgent) IsMobile() bool

IsMobile returns true if the user agent is a mobile device.

type VisitorStats added in v1.5.0

type VisitorStats struct {
	Stats

	PlatformDesktop         int     `db:"platform_desktop" json:"platform_desktop"`
	PlatformMobile          int     `db:"platform_mobile" json:"platform_mobile"`
	PlatformUnknown         int     `db:"platform_unknown" json:"platform_unknown"`
	RelativePlatformDesktop float64 `db:"-" json:"relative_platform_desktop"`
	RelativePlatformMobile  float64 `db:"-" json:"relative_platform_mobile"`
	RelativePlatformUnknown float64 `db:"-" json:"relative_platform_unknown"`
}

VisitorStats is the visitor count for each path on each day and platform and it is used to calculate the total visitor count for each day.

type VisitorTimeStats added in v1.5.0

type VisitorTimeStats struct {
	Stats

	Hour int `db:"hour" json:"hour"`
}

VisitorTimeStats is the visitor count for each path on each day and hour (ranging from 0 to 23).

Directories

Path Synopsis
demos

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL