moved things around, added storage
This commit is contained in:
parent
45981e603f
commit
213efef45a
523
main.go
523
main.go
@ -1,512 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/dalu/gopiwik/mongo"
|
||||
"github.com/dalu/gopiwik/piwik"
|
||||
"gopkg.in/mgo.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
database = "piwik"
|
||||
siteCol = "sites"
|
||||
visitCol = "visits"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
http.HandleFunc("/piwik.php", func(w http.ResponseWriter, r *http.Request) {
|
||||
pr := ParseV3(r)
|
||||
spew.Dump(pr)
|
||||
})
|
||||
http.Handle("/", http.FileServer(http.Dir("assets")))
|
||||
ms, e := mgo.Dial("localhost")
|
||||
if e != nil {
|
||||
log.Fatal(e)
|
||||
}
|
||||
defer ms.Close()
|
||||
siteStorage := mongo.NewSiteStorage(ms, database, siteCol)
|
||||
visitStorage := mongo.NewVisitStorage(ms, database, visitCol)
|
||||
ph := piwik.NewPiwikHandler(siteStorage, visitStorage)
|
||||
http.Handle("/", ph)
|
||||
http.ListenAndServe(":8080", nil)
|
||||
}
|
||||
|
||||
type V3Visit struct {
|
||||
SiteID string //idsite
|
||||
Record bool //rec
|
||||
URL string //url
|
||||
ActionName string //action_anem
|
||||
VisitorID string //_id
|
||||
Referrer string //urlref
|
||||
CustomVars map[string]interface{} //_cvar
|
||||
VisitsCount string //_idvc
|
||||
ViewTime time.Time //_viewts
|
||||
VisitorFirstVisitTime time.Time //_idts
|
||||
CampaignName string //_rcn
|
||||
CampaignKeyword string //_rck
|
||||
Resolution string //res
|
||||
LocalHour string //h
|
||||
LocalMinute string //m
|
||||
LocalSeconds string //s
|
||||
LocalTimeUTC time.Time
|
||||
Plugins struct {
|
||||
Flash bool //fla
|
||||
Java bool //java
|
||||
Director bool //dir
|
||||
Quicktime bool //qt
|
||||
RealPlayer bool //realp
|
||||
PDF bool //pdf
|
||||
WindowsMedia bool //wma
|
||||
Gears bool //gears
|
||||
Silverlight bool //ag
|
||||
}
|
||||
SupportsCookies bool //cookie
|
||||
UserAgent string //ua
|
||||
Language string //lang
|
||||
UserID string //uid
|
||||
CustomUserID string //cid
|
||||
NewVisit bool //new_visit
|
||||
|
||||
PageCustomVars map[string]interface{} //cvar
|
||||
Link string //link
|
||||
Download string //download
|
||||
Search string //search
|
||||
SearchCategory string //search_cat
|
||||
SearchCount string //search_count
|
||||
PageViewID string //pv_id
|
||||
GoalID string //idgoal
|
||||
Revenue string //revenue
|
||||
GenerationTime string //gt_ms
|
||||
Characterset string //cs
|
||||
|
||||
EventCategory string //e_c
|
||||
EventAction string //e_a
|
||||
EventName string //e_n
|
||||
EventValue string //e_v
|
||||
|
||||
ContentName string //c_n
|
||||
ContentPiece string //c_p
|
||||
ContentTarget string //c_t
|
||||
ContentInteraction string //c_i
|
||||
|
||||
ECommerceID string // ec_id
|
||||
ECommerceItems [][]string // ec_items
|
||||
ECommerceSubTotal string // ec_st
|
||||
ECommerceTax string // ec_tx
|
||||
ECommerceShipping string // ec_sh
|
||||
ECommerceDiscount string // ec_dt
|
||||
ECommerceTime time.Time // ec_ts
|
||||
|
||||
TokenAuth string //token_auth
|
||||
CustomIP string //cip
|
||||
CustomDateTime string //cdt
|
||||
CustomCountry string //country
|
||||
CustomRegion string //region
|
||||
CustomCity string //city
|
||||
CustomLatitude string //lat
|
||||
CustomLongitude string //long
|
||||
|
||||
MediaID string // ma_id
|
||||
MediaTitle string // ma_ti
|
||||
MediaResource string // ma_re
|
||||
MediaType string // ma_mt
|
||||
MediaPlayerName string // ma_pn
|
||||
MediaSecondsPlayingTime string // ma_st
|
||||
MediaLength string // ma_le
|
||||
MediaProgress string // ma_ps
|
||||
MediaTimeUntilPlay string // ma_ttp
|
||||
MediaWidth string // ma_w
|
||||
MediaHeight string // ma_h
|
||||
MediaFullscreen bool // ma_fs
|
||||
|
||||
SendImage string //send_image
|
||||
}
|
||||
|
||||
func ParseV3(r *http.Request) *V3Visit {
|
||||
/*
|
||||
https://developer.piwik.org/api-reference/tracking-api
|
||||
*/
|
||||
|
||||
v3 := new(V3Visit)
|
||||
// (required) — The ID of the website we're tracking a visit/action for.
|
||||
v3.SiteID = r.URL.Query().Get("idsite")
|
||||
|
||||
// (required) — Required for tracking, must be set to one, eg, &rec=1.
|
||||
if r.URL.Query().Get("rec") == "1" {
|
||||
v3.Record = true
|
||||
} else {
|
||||
v3.Record = false
|
||||
}
|
||||
|
||||
// (required) — The full URL for the current action.
|
||||
v3.URL = r.URL.Query().Get("url")
|
||||
|
||||
// (recommended) — The title of the action being tracked.
|
||||
// It is possible to use slashes / to set one or several categories for this action.
|
||||
// For example, Help / Feedback will create the Action Feedback in the category Help.
|
||||
v3.ActionName = r.URL.Query().Get("action_name")
|
||||
|
||||
// (recommended) — The unique visitor ID, must be a 16 characters hexadecimal string.
|
||||
// Every unique visitor must be assigned a different ID and this ID must not change after it is assigned.
|
||||
// If this value is not set Piwik will still track visits, but the unique visitors metric might be less accurate.
|
||||
v3.VisitorID = r.URL.Query().Get("_id")
|
||||
|
||||
/*
|
||||
r.URL.Query().Get("rand") // (recommended) — Meant to hold a random value that is generated before each request. Using it helps avoid the tracking request being cached by the browser or a proxy.
|
||||
r.URL.Query().Get("apiv") // (recommended) — The parameter &apiv=1 defines the api version to use (currently always set to 1)
|
||||
*/
|
||||
|
||||
// The full HTTP Referrer URL.
|
||||
// This value is used to determine how someone got to your website (ie, through a website, search engine or campaign).
|
||||
v3.Referrer = r.URL.Query().Get("urlref")
|
||||
|
||||
// Visit scope custom variables.
|
||||
// This is a JSON encoded string of the custom variable array (see below for an example value).
|
||||
if e := json.Unmarshal([]byte(r.URL.Query().Get("_cvar")), v3.CustomVars);e != nil {
|
||||
log.Println(e)
|
||||
}
|
||||
|
||||
// The current count of visits for this visitor.
|
||||
// To set this value correctly, it would be required to store the value for each visitor in your application (using sessions or persisting in a database).
|
||||
// Then you would manually increment the counts by one on each new visit or "session", depending on how you choose to define a visit.
|
||||
// This value is used to populate the report Visitors > Engagement > Visits by visit number.
|
||||
v3.VisitsCount = r.URL.Query().Get("_idvc")
|
||||
|
||||
// The UNIX timestamp of this visitor's previous visit. This parameter is used to populate the report Visitors > Engagement > Visits by days since last visit.
|
||||
v3.ViewTime = stringToTime(r.URL.Query().Get("_viewts"))
|
||||
|
||||
// The UNIX timestamp of this visitor's first visit. This could be set to the date where the user first started using your software/app, or when he/she created an account.
|
||||
// This parameter is used to populate the Goals > Days to Conversion report.
|
||||
v3.VisitorFirstVisitTime = stringToTime(r.URL.Query().Get("_idts"))
|
||||
|
||||
// The Campaign name (see Tracking Campaigns).
|
||||
// Used to populate the Referrers > Campaigns report.
|
||||
// Note: this parameter will only be used for the first pageview of a visit.
|
||||
v3.CampaignName = r.URL.Query().Get("_rcn")
|
||||
|
||||
// The Campaign Keyword (see Tracking Campaigns).
|
||||
// Used to populate the Referrers > Campaigns report (clicking on a campaign loads all keywords for this campaign).
|
||||
// Note: this parameter will only be used for the first pageview of a visit.
|
||||
v3.CampaignKeyword = r.URL.Query().Get("_rck")
|
||||
|
||||
// The resolution of the device the visitor is using, eg 1280x1024.
|
||||
v3.Resolution = r.URL.Query().Get("res")
|
||||
|
||||
// The current hour (local time).
|
||||
v3.LocalHour = r.URL.Query().Get("h")
|
||||
|
||||
// The current minute (local time).
|
||||
v3.LocalMinute = r.URL.Query().Get("m")
|
||||
|
||||
// The current second (local time).
|
||||
v3.LocalSeconds = r.URL.Query().Get("s")
|
||||
|
||||
v3.LocalTimeUTC = time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), atoi(r.URL.Query().Get("h")), atoi(r.URL.Query().Get("m")), atoi(r.URL.Query().Get("s")), 0, time.UTC)
|
||||
|
||||
// plugins used by the visitor can be specified by setting the following parameters to 1
|
||||
|
||||
// Flash
|
||||
if r.URL.Query().Get("fla") == "1" {
|
||||
v3.Plugins.Flash = true
|
||||
}
|
||||
|
||||
// Java
|
||||
if r.URL.Query().Get("java") == "1" {
|
||||
v3.Plugins.Java = true
|
||||
}
|
||||
|
||||
// Director
|
||||
if r.URL.Query().Get("dir") == "1" {
|
||||
v3.Plugins.Director = true
|
||||
}
|
||||
|
||||
// Quicktime
|
||||
if r.URL.Query().Get("qt") == "1" {
|
||||
v3.Plugins.Quicktime = true
|
||||
}
|
||||
|
||||
// Real Player
|
||||
if r.URL.Query().Get("realp") == "1" {
|
||||
v3.Plugins.RealPlayer = true
|
||||
}
|
||||
|
||||
// PDF
|
||||
if r.URL.Query().Get("pdf") == "1" {
|
||||
v3.Plugins.PDF = true
|
||||
}
|
||||
|
||||
// Windows Media
|
||||
if r.URL.Query().Get("wma") == "1" {
|
||||
v3.Plugins.WindowsMedia = true
|
||||
}
|
||||
|
||||
// Gears
|
||||
if r.URL.Query().Get("gears") == "1" {
|
||||
v3.Plugins.Gears = true
|
||||
}
|
||||
|
||||
// Silverlight
|
||||
if r.URL.Query().Get("ag") == "1" {
|
||||
v3.Plugins.Silverlight = true
|
||||
}
|
||||
|
||||
// when set to 1, the visitor's client is known to support cookies.
|
||||
if r.URL.Query().Get("cookie") == "1" {
|
||||
v3.SupportsCookies = true
|
||||
}
|
||||
|
||||
// An override value for the User-Agent HTTP header field. The user agent is used to detect the operating system and browser used.
|
||||
if r.URL.Query().Get("ua") != "" {
|
||||
v3.UserAgent = r.URL.Query().Get("ua")
|
||||
} else {
|
||||
v3.UserAgent = r.UserAgent()
|
||||
}
|
||||
|
||||
// An override value for the Accept-Language HTTP header field. This value is used to detect the visitor's country if GeoIP is not enabled.
|
||||
if r.URL.Query().Get("lang") != "" {
|
||||
v3.Language = r.URL.Query().Get("lang")
|
||||
} else {
|
||||
v3.Language = r.Header.Get("Accept-Language")
|
||||
}
|
||||
|
||||
// defines the User ID for this request.
|
||||
// User ID is any non empty unique string identifying the user (such as an email address or a username).
|
||||
// To access this value, users must be logged-in in your system so you can fetch this user ID from your system, and pass it to Piwik.
|
||||
// The User ID appears in the visitor log, the Visitor profile, and you can Segment reports for one or several User ID (userId segment).
|
||||
// When specified, the User ID will be "enforced".
|
||||
// This means that if there is no recent visit with this User ID, a new one will be created.
|
||||
// If a visit is found in the last 30 minutes with your specified User ID, then the new action will be recorded to this existing visit.
|
||||
v3.UserID = r.URL.Query().Get("uid")
|
||||
|
||||
// defines the visitor ID for this request.
|
||||
// You must set this value to exactly a 16 character hexadecimal string (containing only characters 01234567890abcdefABCDEF).
|
||||
// We recommended to set the User ID via uid rather than use this cid
|
||||
v3.CustomUserID = r.URL.Query().Get("cid")
|
||||
|
||||
// If set to 1, will force a new visit to be created for this action. This feature is also available in JavaScript.
|
||||
if r.URL.Query().Get("new_visit") == "1" {
|
||||
v3.NewVisit = true
|
||||
}
|
||||
|
||||
/*
|
||||
// ? scopes?
|
||||
dimension := make(map[string]string)
|
||||
for k, v := range r.URL.Query() {
|
||||
if strings.HasPrefix(k, "dimension") {
|
||||
dimension[strings.TrimPrefix(k, "dimension")] = v
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
Optional Action info (measure Page view, Outlink, Download, Site search)
|
||||
*/
|
||||
|
||||
// Page scope custom variables. This is a JSON encoded string of the custom variable array (see below for an example value).
|
||||
json.Unmarshal([]byte(r.URL.Query().Get("cvar")), v3.PageCustomVars)
|
||||
|
||||
// An external URL the user has opened.
|
||||
// Used for tracking outlink clicks.
|
||||
// We recommend to also set the url parameter to this same value.
|
||||
v3.Link = r.URL.Query().Get("link")
|
||||
|
||||
// URL of a file the user has downloaded.
|
||||
// Used for tracking downloads.
|
||||
// We recommend to also set the url parameter to this same value.
|
||||
v3.Download = r.URL.Query().Get("download")
|
||||
|
||||
// The Site Search keyword.
|
||||
// When specified, the request will not be tracked as a normal pageview but will instead be tracked as a Site Search request.
|
||||
v3.Search = r.URL.Query().Get("search")
|
||||
|
||||
// when search is specified, you can optionally specify a search category with this parameter.
|
||||
v3.SearchCategory = r.URL.Query().Get("search_cat")
|
||||
|
||||
// when search is specified, we also recommend to set the search_count to the number of search results displayed on the results page.
|
||||
// When keywords are tracked with &search_count=0 they will appear in the "No Result Search Keyword" report.
|
||||
v3.SearchCount = r.URL.Query().Get("search_count")
|
||||
|
||||
// Accepts a six character unique ID that identifies which actions were performed on a specific page view.
|
||||
// When a page was viewed, all following tracking requests (such as events) during that page view should use the same pageview ID.
|
||||
// Once another page was viewed a new unique ID should be generated.
|
||||
// Use [0-9a-Z] as possible characters for the unique ID.
|
||||
v3.PageViewID = r.URL.Query().Get("pv_id")
|
||||
|
||||
// If specified, the tracking request will trigger a conversion for the goal of the website being tracked with this ID.
|
||||
v3.GoalID = r.URL.Query().Get("idgoal")
|
||||
|
||||
// A monetary value that was generated as revenue by this goal conversion.
|
||||
// Only used if idgoal is specified in the request.
|
||||
v3.Revenue = r.URL.Query().Get("revenue")
|
||||
|
||||
// The amount of time it took the server to generate this action, in milliseconds.
|
||||
// This value is used to process the Page speed report Avg. generation time column in the Page URL and Page Title reports,
|
||||
// as well as a site wide running average of the speed of your server.
|
||||
// Note: when using the JavaScript tracker this value is set to the time for server to generate response + the time for client to download response.
|
||||
v3.GenerationTime = r.URL.Query().Get("gt_ms")
|
||||
|
||||
// The charset of the page being tracked.
|
||||
// Specify the charset if the data you send to Piwik is encoded in a different character set than the default utf-8.
|
||||
v3.Characterset = r.URL.Query().Get("cs")
|
||||
|
||||
/*
|
||||
Optional Event Tracking info
|
||||
*/
|
||||
|
||||
// The event category. Must not be empty. (eg. Videos, Music, Games...)
|
||||
v3.EventCategory = r.URL.Query().Get("e_c")
|
||||
|
||||
// The event action. Must not be empty. (eg. Play, Pause, Duration, Add Playlist, Downloaded, Clicked...)
|
||||
v3.EventAction = r.URL.Query().Get("e_a")
|
||||
|
||||
// The event name. (eg. a Movie name, or Song name, or File name...)
|
||||
v3.EventName = r.URL.Query().Get("e_n")
|
||||
|
||||
// The event value. Must be a float or integer value (numeric), not a string.
|
||||
v3.EventValue = r.URL.Query().Get("e_v")
|
||||
|
||||
/*
|
||||
Optional Content Tracking info
|
||||
*/
|
||||
|
||||
// The name of the content. For instance 'Ad Foo Bar'
|
||||
v3.ContentName = r.URL.Query().Get("c_n")
|
||||
// The actual content piece. For instance the path to an image, video, audio, any text
|
||||
v3.ContentPiece = r.URL.Query().Get("c_p")
|
||||
// The target of the content. For instance the URL of a landing page
|
||||
v3.ContentTarget = r.URL.Query().Get("c_t")
|
||||
// The name of the interaction with the content. For instance a 'click'
|
||||
v3.ContentInteraction = r.URL.Query().Get("c_i")
|
||||
|
||||
// Optional Ecommerce info
|
||||
// you must set &idgoal=0 in the request to track an ecommerce interaction: cart update or an ecommerce order.
|
||||
if r.URL.Query().Get("idgoal") == "0" {
|
||||
// The unique string identifier for the ecommerce order (required when tracking an ecommerce order)
|
||||
v3.ECommerceID = r.URL.Query().Get("ec_id")
|
||||
|
||||
// Items in the Ecommerce order.
|
||||
// This is a JSON encoded array of items. Each item is an array with the following info in this order: item sku, item name, item category, item price, item quantity.
|
||||
json.Unmarshal([]byte(r.URL.Query().Get("ec_items")), v3.ECommerceItems)
|
||||
|
||||
// The grand total for the ecommerce order (required when tracking an ecommerce order)
|
||||
v3.Revenue = r.URL.Query().Get("revenue")
|
||||
|
||||
// The sub total of the order; excludes shipping.
|
||||
v3.ECommerceSubTotal = r.URL.Query().Get("ec_st")
|
||||
|
||||
// Tax Amount of the order
|
||||
v3.ECommerceTax = r.URL.Query().Get("ec_tx")
|
||||
|
||||
// Shipping cost of the Order
|
||||
v3.ECommerceShipping = r.URL.Query().Get("ec_sh")
|
||||
|
||||
// Discount offered
|
||||
v3.ECommerceDiscount = r.URL.Query().Get("ec_dt")
|
||||
|
||||
// The UNIX timestamp of this customer's last ecommerce order.
|
||||
// This value is used to process the "Days since last order" report.
|
||||
v3.ECommerceTime = stringToTime(r.URL.Query().Get("_ects"))
|
||||
}
|
||||
|
||||
/*
|
||||
Other parameters (require authentication via token_auth)
|
||||
*/
|
||||
|
||||
// 32 character authorization key used to authenticate the API request.
|
||||
v3.TokenAuth = r.URL.Query().Get("token_auth")
|
||||
|
||||
// Override value for the visitor IP (both IPv4 and IPv6 notations supported).
|
||||
v3.CustomIP = r.URL.Query().Get("cip")
|
||||
|
||||
// Override for the datetime of the request (normally the current time is used).
|
||||
// This can be used to record visits and page views in the past.
|
||||
// The expected format is either a datetime such as: 2011-04-05 00:11:42 (remember to URL encode the value!), or a valid UNIX timestamp such as 1301919102.
|
||||
// The datetime must be sent in UTC timezone.
|
||||
// Note: if you record data in the past, you will need to force Piwik to re-process reports for the past dates.
|
||||
// If you set cdt to a datetime older than 24 hours then token_auth must be set.
|
||||
// If you set cdt with a datetime in the last 24 hours then you don't need to pass token_auth.
|
||||
v3.CustomDateTime = r.URL.Query().Get("cdt")
|
||||
|
||||
// An override value for the country. Should be set to the two letter country code of the visitor (lowercase), eg fr, de, us.
|
||||
v3.CustomCountry = r.URL.Query().Get("country")
|
||||
|
||||
// An override value for the region. Should be set to the two letter region code as defined by MaxMind's GeoIP databases. See here for a list of them for every country (the region codes are located in the second column, to the left of the region name and to the right of the country code).
|
||||
v3.CustomRegion = r.URL.Query().Get("region")
|
||||
|
||||
// An override value for the city. The name of the city the visitor is located in, eg, Tokyo.
|
||||
v3.CustomCity = r.URL.Query().Get("city")
|
||||
|
||||
// An override value for the visitor's latitude, eg 22.456.
|
||||
v3.CustomLatitude = r.URL.Query().Get("lat")
|
||||
|
||||
// An override value for the visitor's longitude, eg 22.456.
|
||||
v3.CustomLongitude = r.URL.Query().Get("long")
|
||||
|
||||
/*
|
||||
Media Analytics parameters
|
||||
https://developer.piwik.org/guides/media-analytics/custom-player#media-analytics-http-tracking-api-reference
|
||||
*/
|
||||
|
||||
// A unique id that is always the same while playing a media. As soon as the played media changes (new video or audio started), this ID has to change.
|
||||
v3.MediaID = r.URL.Query().Get("ma_id")
|
||||
|
||||
// The name / title of the media.
|
||||
v3.MediaTitle = r.URL.Query().Get("ma_ti")
|
||||
|
||||
// The URL of the media resource.
|
||||
v3.MediaResource = r.URL.Query().Get("ma_re")
|
||||
|
||||
// video or audio depending on the type of the media.
|
||||
v3.MediaType = r.URL.Query().Get("ma_mt")
|
||||
|
||||
// The name of the media player, for example html5.
|
||||
v3.MediaPlayerName = r.URL.Query().Get("ma_pn")
|
||||
|
||||
// The time in seconds for how long a user has been playing this media.
|
||||
// This number should typically increase when you send a media tracking request.
|
||||
// It should be 0 if the media was only visible/impressed but not played.
|
||||
// Do not increase this number when a media is paused.
|
||||
v3.MediaSecondsPlayingTime = r.URL.Query().Get("ma_st")
|
||||
|
||||
// The duration (the length) of the media in seconds. For example if a video is 90 seconds long, the value should be 90.
|
||||
v3.MediaLength = r.URL.Query().Get("ma_le")
|
||||
|
||||
// The progress / current position within the media. Defines basically at which position within the total length the user is currently playing.
|
||||
v3.MediaProgress = r.URL.Query().Get("ma_ps")
|
||||
|
||||
// Defines after how many seconds the user has started playing this media.
|
||||
// For example a user might have seen the poster of the video for 30 seconds before a user actually pressed the play button.
|
||||
v3.MediaTimeUntilPlay = r.URL.Query().Get("ma_ttp")
|
||||
|
||||
// The resolution width of the media in pixels. Only recommended to be set for videos.
|
||||
v3.MediaWidth = r.URL.Query().Get("ma_w")
|
||||
|
||||
// The resolution height of the media in pixels. Only recommended to be set for videos.
|
||||
v3.MediaHeight = r.URL.Query().Get("ma_h")
|
||||
|
||||
// Should be 0 or 1 and defines whether the media is currently viewed in full screen. Only recommended to be set for videos.
|
||||
switch r.URL.Query().Get("ma_fs") {
|
||||
case "0":
|
||||
v3.MediaFullscreen = false
|
||||
case "1":
|
||||
v3.MediaFullscreen = true
|
||||
default:
|
||||
v3.MediaFullscreen = false
|
||||
}
|
||||
|
||||
// If set to 0 (send_image=0) Piwik will respond with a HTTP 204 response code instead of a GIF image.
|
||||
// This improves performance and can fix errors if images are not allowed to be obtained directly (eg Chrome Apps).
|
||||
// Available since Piwik 2.10.0
|
||||
v3.SendImage = r.URL.Query().Get("send_image")
|
||||
|
||||
return v3
|
||||
|
||||
/*
|
||||
r.URL.Query().Get("") //
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
func stringToTime(s string) time.Time {
|
||||
i, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
return time.Time{}
|
||||
}
|
||||
return time.Unix(i, 0)
|
||||
}
|
||||
|
||||
func atoi(a string) int {
|
||||
i, err := strconv.Atoi(a)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
87
mongo/site.go
Normal file
87
mongo/site.go
Normal file
@ -0,0 +1,87 @@
|
||||
package mongo
|
||||
|
||||
import (
|
||||
"github.com/dalu/gopiwik/piwik"
|
||||
"gopkg.in/mgo.v2"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
func NewSiteStorage(ms *mgo.Session, db, col string) SiteStorage {
|
||||
return SiteStorage{
|
||||
ms: ms.Clone(),
|
||||
db: db,
|
||||
col: col,
|
||||
}
|
||||
}
|
||||
|
||||
type SiteStorage struct {
|
||||
ms *mgo.Session
|
||||
db, col string
|
||||
}
|
||||
|
||||
func (s SiteStorage) Add(site *piwik.Site) error {
|
||||
ms := s.ms.Copy()
|
||||
defer ms.Close()
|
||||
c := ms.DB(s.db).C(s.col)
|
||||
site.ID = bson.NewObjectId().Hex()
|
||||
return c.Insert(site)
|
||||
}
|
||||
|
||||
func (s SiteStorage) Remove(site *piwik.Site) error {
|
||||
ms := s.ms.Copy()
|
||||
defer ms.Close()
|
||||
c := ms.DB(s.db).C(s.col)
|
||||
return c.RemoveId(site.ID)
|
||||
|
||||
}
|
||||
|
||||
func (s SiteStorage) Update(site *piwik.Site) error {
|
||||
ms := s.ms.Copy()
|
||||
defer ms.Close()
|
||||
c := ms.DB(s.db).C(s.col)
|
||||
return c.UpdateId(site.ID, site)
|
||||
}
|
||||
|
||||
func (s SiteStorage) List() ([]*piwik.Site, error) {
|
||||
ms := s.ms.Copy()
|
||||
defer ms.Close()
|
||||
c := ms.DB(s.db).C(s.col)
|
||||
sites := []*piwik.Site{}
|
||||
if e := c.Find(nil).All(&sites); e != nil {
|
||||
return sites, e
|
||||
}
|
||||
return sites, nil
|
||||
}
|
||||
|
||||
func (s SiteStorage) FindId(id string) (*piwik.Site, error) {
|
||||
ms := s.ms.Copy()
|
||||
defer ms.Close()
|
||||
site := new(piwik.Site)
|
||||
c := ms.DB(s.db).C(s.col)
|
||||
if e := c.FindId(id).One(site); e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return site, nil
|
||||
}
|
||||
|
||||
func (s SiteStorage) Find(query map[string]interface{}) (*piwik.Site, error) {
|
||||
ms := s.ms.Copy()
|
||||
defer ms.Close()
|
||||
c := ms.DB(s.db).C(s.col)
|
||||
site := new(piwik.Site)
|
||||
if e := c.Find(query).One(site); e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return site, nil
|
||||
}
|
||||
|
||||
func (s SiteStorage) FindAll(query map[string]interface{}) ([]*piwik.Site, error) {
|
||||
ms := s.ms.Copy()
|
||||
defer ms.Close()
|
||||
c := ms.DB(s.db).C(s.col)
|
||||
sites := []*piwik.Site{}
|
||||
if e := c.Find(query).All(&sites); e != nil {
|
||||
return sites, e
|
||||
}
|
||||
return sites, nil
|
||||
}
|
51
mongo/visit.go
Normal file
51
mongo/visit.go
Normal file
@ -0,0 +1,51 @@
|
||||
package mongo
|
||||
|
||||
import (
|
||||
"github.com/dalu/gopiwik/piwik"
|
||||
"gopkg.in/mgo.v2"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
|
||||
func NewVisitStorage(ms *mgo.Session, db, col string) VisitStorage {
|
||||
return VisitStorage{
|
||||
ms: ms.Clone(),
|
||||
db: db,
|
||||
col: col,
|
||||
}
|
||||
}
|
||||
|
||||
type VisitStorage struct {
|
||||
ms *mgo.Session
|
||||
db, col string
|
||||
}
|
||||
|
||||
func (s VisitStorage) Add(visit *piwik.Visit) error {
|
||||
ms := s.ms.Copy()
|
||||
defer ms.Close()
|
||||
c := ms.DB(s.db).C(s.col)
|
||||
visit.ID = bson.NewObjectId().Hex()
|
||||
return c.Insert(visit)
|
||||
}
|
||||
|
||||
func (s VisitStorage) Find(query map[string]interface{}) (*piwik.Visit, error) {
|
||||
ms := s.ms.Copy()
|
||||
defer ms.Close()
|
||||
c := ms.DB(s.db).C(s.col)
|
||||
visit := new(piwik.Visit)
|
||||
if e := c.Find(query).One(visit); e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return visit, nil
|
||||
}
|
||||
|
||||
func (s VisitStorage) FindAll(query map[string]interface{}) ([]*piwik.Visit, error) {
|
||||
ms := s.ms.Copy()
|
||||
defer ms.Close()
|
||||
c := ms.DB(s.db).C(s.col)
|
||||
visits := []*piwik.Visit{}
|
||||
if e := c.Find(query).All(visits); e != nil {
|
||||
return nil, e
|
||||
}
|
||||
return visits, nil
|
||||
|
||||
}
|
120
piwik/handler.go
Normal file
120
piwik/handler.go
Normal file
@ -0,0 +1,120 @@
|
||||
package piwik
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"encoding/json"
|
||||
"os"
|
||||
)
|
||||
|
||||
type PiwikHandler struct {
|
||||
fileServer http.Handler
|
||||
siteStorage SiteStorageInterface
|
||||
visitStorage VisitStorageInterface
|
||||
}
|
||||
|
||||
func NewPiwikHandler(ss SiteStorageInterface, vs VisitStorageInterface) *PiwikHandler {
|
||||
return &PiwikHandler{
|
||||
fileServer: http.FileServer(http.Dir("assets")),
|
||||
siteStorage: ss,
|
||||
visitStorage: vs,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *PiwikHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
switch r.URL.Path {
|
||||
case "/piwik.php":
|
||||
h.handlePiwik(w, r)
|
||||
default:
|
||||
h.fileServer.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
default:
|
||||
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *PiwikHandler) handlePiwik(w http.ResponseWriter, r *http.Request) {
|
||||
pr := ParseV3(r)
|
||||
v := &Visit{
|
||||
SiteID: pr.SiteID,
|
||||
URL: pr.URL,
|
||||
ActionName: pr.ActionName,
|
||||
VisitorID: pr.VisitorID,
|
||||
Referrer: pr.Referrer,
|
||||
CustomVars: pr.CustomVars,
|
||||
VisitsCount: pr.VisitsCount,
|
||||
ViewTime: pr.ViewTime,
|
||||
VisitorFirstVisitTime: pr.VisitorFirstVisitTime,
|
||||
CampaignName: pr.CampaignName,
|
||||
CampaignKeyword: pr.CampaignKeyword,
|
||||
Resolution: pr.Resolution,
|
||||
LocalHour: pr.LocalHour,
|
||||
LocalMinute: pr.LocalMinute,
|
||||
LocalSeconds: pr.LocalSeconds,
|
||||
LocalTimeUTC: pr.LocalTimeUTC,
|
||||
Plugins: pr.Plugins,
|
||||
SupportsCookies: pr.SupportsCookies,
|
||||
UserAgent: pr.UserAgent,
|
||||
Language: pr.Language,
|
||||
UserID: pr.UserID,
|
||||
CustomUserID: pr.CustomUserID,
|
||||
NewVisit: pr.NewVisit,
|
||||
PageCustomVars: pr.PageCustomVars,
|
||||
Link: pr.Link,
|
||||
Download: pr.Download,
|
||||
Search: pr.Search,
|
||||
SearchCategory: pr.SearchCategory,
|
||||
SearchCount: pr.SearchCount,
|
||||
PageViewID: pr.PageViewID,
|
||||
GoalID: pr.GoalID,
|
||||
Revenue: pr.Revenue,
|
||||
GenerationTime: pr.GenerationTime,
|
||||
Characterset: pr.Characterset,
|
||||
EventCategory: pr.EventCategory,
|
||||
EventAction: pr.EventAction,
|
||||
EventName: pr.EventName,
|
||||
EventValue: pr.EventValue,
|
||||
ContentName: pr.ContentName,
|
||||
ContentPiece: pr.ContentPiece,
|
||||
ContentTarget: pr.ContentTarget,
|
||||
ContentInteraction: pr.ContentInteraction,
|
||||
ECommerceID: pr.ECommerceID,
|
||||
ECommerceItems: pr.ECommerceItems,
|
||||
ECommerceSubTotal: pr.ECommerceSubTotal,
|
||||
ECommerceTax: pr.ECommerceTax,
|
||||
ECommerceShipping: pr.ECommerceShipping,
|
||||
ECommerceDiscount: pr.ECommerceDiscount,
|
||||
ECommerceTime: pr.ECommerceTime,
|
||||
TokenAuth: pr.TokenAuth,
|
||||
CustomIP: pr.CustomIP,
|
||||
CustomDateTime: pr.CustomDateTime,
|
||||
CustomCountry: pr.CustomCountry,
|
||||
CustomRegion: pr.CustomRegion,
|
||||
CustomCity: pr.CustomCity,
|
||||
CustomLatitude: pr.CustomLatitude,
|
||||
CustomLongitude: pr.CustomLongitude,
|
||||
MediaID: pr.MediaID,
|
||||
MediaTitle: pr.MediaTitle,
|
||||
MediaResource: pr.MediaResource,
|
||||
MediaType: pr.MediaType,
|
||||
MediaPlayerName: pr.MediaPlayerName,
|
||||
MediaSecondsPlayingTime: pr.MediaSecondsPlayingTime,
|
||||
MediaLength: pr.MediaLength,
|
||||
MediaProgress: pr.MediaProgress,
|
||||
MediaTimeUntilPlay: pr.MediaTimeUntilPlay,
|
||||
MediaWidth: pr.MediaWidth,
|
||||
MediaHeight: pr.MediaHeight,
|
||||
MediaFullscreen: pr.MediaFullscreen,
|
||||
}
|
||||
if e := h.visitStorage.Add(v); e != nil {
|
||||
log.Println(e)
|
||||
}
|
||||
if pr.SendImage == "0" {
|
||||
w.WriteHeader(204)
|
||||
}
|
||||
json.NewEncoder(os.Stdout).Encode(v)
|
||||
}
|
500
piwik/parse.go
Normal file
500
piwik/parse.go
Normal file
@ -0,0 +1,500 @@
|
||||
package piwik
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type V3Visit struct {
|
||||
SiteID string `json:"site_id"` //idsite
|
||||
Record bool `json:"record"` //rec
|
||||
URL string `json:"url"` //url
|
||||
ActionName string `json:"action_name"` //action_anem
|
||||
VisitorID string `json:"visitor_id"` //_id
|
||||
Referrer string `json:"referrer"` //urlref
|
||||
CustomVars map[string]interface{} `json:"custom_vars"` //_cvar
|
||||
VisitsCount string `json:"visits_count"` //_idvc
|
||||
ViewTime time.Time `json:"view_time"` //_viewts
|
||||
VisitorFirstVisitTime time.Time `json:"visitor_first_visit_time"` //_idts
|
||||
CampaignName string `json:"campaign_name"` //_rcn
|
||||
CampaignKeyword string `json:"campaign_keyword"` //_rck
|
||||
Resolution string `json:"resolution"` //res
|
||||
LocalHour string `json:"local_hour"` //h
|
||||
LocalMinute string `json:"local_minute"` //m
|
||||
LocalSeconds string `json:"local_seconds"` //s
|
||||
LocalTimeUTC time.Time `json:"local_time_utc"`
|
||||
Plugins *Plugins `json:"plugins"`
|
||||
SupportsCookies bool `json:"supports_cookies"` //cookie
|
||||
UserAgent string `json:"user_agent"` //ua
|
||||
Language string `json:"language"` //lang
|
||||
UserID string `json:"user_id"` //uid
|
||||
CustomUserID string `json:"custom_user_id"` //cid
|
||||
NewVisit bool `json:"new_visit"` //new_visit
|
||||
PageCustomVars map[string]interface{} `json:"page_custom_vars"` //cvar
|
||||
Link string `json:"link"` //link
|
||||
Download string `json:"download"` //download
|
||||
Search string `json:"search"` //search
|
||||
SearchCategory string `json:"search_category"` //search_cat
|
||||
SearchCount string `json:"search_count"` //search_count
|
||||
PageViewID string `json:"page_view_id"` //pv_id
|
||||
GoalID string `json:"goal_id"` //idgoal
|
||||
Revenue string `json:"revenue"` //revenue
|
||||
GenerationTime string `json:"generation_time"` //gt_ms
|
||||
Characterset string `json:"characterset"` //cs
|
||||
EventCategory string `json:"event_category"` //e_c
|
||||
EventAction string `json:"event_action"` //e_a
|
||||
EventName string `json:"event_name"` //e_n
|
||||
EventValue string `json:"event_value"` //e_v
|
||||
ContentName string `json:"content_name"` //c_n
|
||||
ContentPiece string `json:"content_piece"` //c_p
|
||||
ContentTarget string `json:"content_target"` //c_t
|
||||
ContentInteraction string `json:"content_interaction"` //c_i
|
||||
ECommerceID string `json:"ecommerce_id"` // ec_id
|
||||
ECommerceItems [][]string `json:"ecommerce_items"` // ec_items
|
||||
ECommerceSubTotal string `json:"ecommerce_sub_total"` // ec_st
|
||||
ECommerceTax string `json:"ecommerce_tax"` // ec_tx
|
||||
ECommerceShipping string `json:"ecommerce_shipping"` // ec_sh
|
||||
ECommerceDiscount string `json:"ecommerce_discount"` // ec_dt
|
||||
ECommerceTime time.Time `json:"ecommerce_time"` // ec_ts
|
||||
TokenAuth string `json:"token_auth"` //token_auth
|
||||
CustomIP string `json:"custom_ip"` //cip
|
||||
CustomDateTime string `json:"custom_date_time"` //cdt
|
||||
CustomCountry string `json:"custom_country"` //country
|
||||
CustomRegion string `json:"custom_region"` //region
|
||||
CustomCity string `json:"custom_city"` //city
|
||||
CustomLatitude string `json:"custom_latitude"` //lat
|
||||
CustomLongitude string `json:"custom_longitude"` //long
|
||||
MediaID string `json:"media_id"` // ma_id
|
||||
MediaTitle string `json:"media_title"` // ma_ti
|
||||
MediaResource string `json:"media_resource"` // ma_re
|
||||
MediaType string `json:"media_type"` // ma_mt
|
||||
MediaPlayerName string `json:"media_player_name"` // ma_pn
|
||||
MediaSecondsPlayingTime string `json:"media_seconds_playing_time"` // ma_st
|
||||
MediaLength string `json:"media_length"` // ma_le
|
||||
MediaProgress string `json:"media_progress"` // ma_ps
|
||||
MediaTimeUntilPlay string `json:"media_time_until_play"` // ma_ttp
|
||||
MediaWidth string `json:"media_width"` // ma_w
|
||||
MediaHeight string `json:"media_height"` // ma_h
|
||||
MediaFullscreen bool `json:"media_fullscreen"` // ma_fs
|
||||
SendImage string `json:"send_image"` //send_image
|
||||
}
|
||||
|
||||
type Plugins struct {
|
||||
Flash bool `json:"flash"` //fla
|
||||
Java bool `json:"java"` //java
|
||||
Director bool `json:"director"` //dir
|
||||
Quicktime bool `json:"quicktime"` //qt
|
||||
RealPlayer bool `json:"real_player"` //realp
|
||||
PDF bool `json:"pdf"` //pdf
|
||||
WindowsMedia bool `json:"windows_media"` //wma
|
||||
Gears bool `json:"gears"` //gears
|
||||
Silverlight bool `json:"silverlight"` //ag
|
||||
}
|
||||
|
||||
func ParseV3(r *http.Request) *V3Visit {
|
||||
/*
|
||||
https://developer.piwik.org/api-reference/tracking-api
|
||||
*/
|
||||
|
||||
v3 := new(V3Visit)
|
||||
// (required) — The ID of the website we're tracking a visit/action for.
|
||||
v3.SiteID = r.URL.Query().Get("idsite")
|
||||
|
||||
// (required) — Required for tracking, must be set to one, eg, &rec=1.
|
||||
if r.URL.Query().Get("rec") == "1" {
|
||||
v3.Record = true
|
||||
} else {
|
||||
v3.Record = false
|
||||
}
|
||||
|
||||
// (required) — The full URL for the current action.
|
||||
v3.URL = r.URL.Query().Get("url")
|
||||
|
||||
// (recommended) — The title of the action being tracked.
|
||||
// It is possible to use slashes / to set one or several categories for this action.
|
||||
// For example, Help / Feedback will create the Action Feedback in the category Help.
|
||||
v3.ActionName = r.URL.Query().Get("action_name")
|
||||
|
||||
// (recommended) — The unique visitor ID, must be a 16 characters hexadecimal string.
|
||||
// Every unique visitor must be assigned a different ID and this ID must not change after it is assigned.
|
||||
// If this value is not set Piwik will still track visits, but the unique visitors metric might be less accurate.
|
||||
v3.VisitorID = r.URL.Query().Get("_id")
|
||||
|
||||
/*
|
||||
r.URL.Query().Get("rand") // (recommended) — Meant to hold a random value that is generated before each request. Using it helps avoid the tracking request being cached by the browser or a proxy.
|
||||
r.URL.Query().Get("apiv") // (recommended) — The parameter &apiv=1 defines the api version to use (currently always set to 1)
|
||||
*/
|
||||
|
||||
// The full HTTP Referrer URL.
|
||||
// This value is used to determine how someone got to your website (ie, through a website, search engine or campaign).
|
||||
v3.Referrer = r.URL.Query().Get("urlref")
|
||||
|
||||
// Visit scope custom variables.
|
||||
// This is a JSON encoded string of the custom variable array (see below for an example value).
|
||||
if r.URL.Query().Get("_cvar") != "" {
|
||||
if e := json.Unmarshal([]byte(r.URL.Query().Get("_cvar")), v3.CustomVars); e != nil {
|
||||
log.Println("Error unmarshalling _cvar", e)
|
||||
}
|
||||
}
|
||||
|
||||
// The current count of visits for this visitor.
|
||||
// To set this value correctly, it would be required to store the value for each visitor in your application (using sessions or persisting in a database).
|
||||
// Then you would manually increment the counts by one on each new visit or "session", depending on how you choose to define a visit.
|
||||
// This value is used to populate the report Visitors > Engagement > Visits by visit number.
|
||||
v3.VisitsCount = r.URL.Query().Get("_idvc")
|
||||
|
||||
// The UNIX timestamp of this visitor's previous visit. This parameter is used to populate the report Visitors > Engagement > Visits by days since last visit.
|
||||
v3.ViewTime = stringToTime(r.URL.Query().Get("_viewts"))
|
||||
|
||||
// The UNIX timestamp of this visitor's first visit. This could be set to the date where the user first started using your software/app, or when he/she created an account.
|
||||
// This parameter is used to populate the Goals > Days to Conversion report.
|
||||
v3.VisitorFirstVisitTime = stringToTime(r.URL.Query().Get("_idts"))
|
||||
|
||||
// The Campaign name (see Tracking Campaigns).
|
||||
// Used to populate the Referrers > Campaigns report.
|
||||
// Note: this parameter will only be used for the first pageview of a visit.
|
||||
v3.CampaignName = r.URL.Query().Get("_rcn")
|
||||
|
||||
// The Campaign Keyword (see Tracking Campaigns).
|
||||
// Used to populate the Referrers > Campaigns report (clicking on a campaign loads all keywords for this campaign).
|
||||
// Note: this parameter will only be used for the first pageview of a visit.
|
||||
v3.CampaignKeyword = r.URL.Query().Get("_rck")
|
||||
|
||||
// The resolution of the device the visitor is using, eg 1280x1024.
|
||||
v3.Resolution = r.URL.Query().Get("res")
|
||||
|
||||
// The current hour (local time).
|
||||
v3.LocalHour = r.URL.Query().Get("h")
|
||||
|
||||
// The current minute (local time).
|
||||
v3.LocalMinute = r.URL.Query().Get("m")
|
||||
|
||||
// The current second (local time).
|
||||
v3.LocalSeconds = r.URL.Query().Get("s")
|
||||
|
||||
v3.LocalTimeUTC = time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), atoi(r.URL.Query().Get("h")), atoi(r.URL.Query().Get("m")), atoi(r.URL.Query().Get("s")), 0, time.UTC)
|
||||
|
||||
// plugins used by the visitor can be specified by setting the following parameters to 1
|
||||
|
||||
v3.Plugins = new(Plugins)
|
||||
|
||||
// Flash
|
||||
if r.URL.Query().Get("fla") == "1" {
|
||||
v3.Plugins.Flash = true
|
||||
}
|
||||
|
||||
// Java
|
||||
if r.URL.Query().Get("java") == "1" {
|
||||
v3.Plugins.Java = true
|
||||
}
|
||||
|
||||
// Director
|
||||
if r.URL.Query().Get("dir") == "1" {
|
||||
v3.Plugins.Director = true
|
||||
}
|
||||
|
||||
// Quicktime
|
||||
if r.URL.Query().Get("qt") == "1" {
|
||||
v3.Plugins.Quicktime = true
|
||||
}
|
||||
|
||||
// Real Player
|
||||
if r.URL.Query().Get("realp") == "1" {
|
||||
v3.Plugins.RealPlayer = true
|
||||
}
|
||||
|
||||
// PDF
|
||||
if r.URL.Query().Get("pdf") == "1" {
|
||||
v3.Plugins.PDF = true
|
||||
}
|
||||
|
||||
// Windows Media
|
||||
if r.URL.Query().Get("wma") == "1" {
|
||||
v3.Plugins.WindowsMedia = true
|
||||
}
|
||||
|
||||
// Gears
|
||||
if r.URL.Query().Get("gears") == "1" {
|
||||
v3.Plugins.Gears = true
|
||||
}
|
||||
|
||||
// Silverlight
|
||||
if r.URL.Query().Get("ag") == "1" {
|
||||
v3.Plugins.Silverlight = true
|
||||
}
|
||||
|
||||
// when set to 1, the visitor's client is known to support cookies.
|
||||
if r.URL.Query().Get("cookie") == "1" {
|
||||
v3.SupportsCookies = true
|
||||
}
|
||||
|
||||
// An override value for the User-Agent HTTP header field. The user agent is used to detect the operating system and browser used.
|
||||
if r.URL.Query().Get("ua") != "" {
|
||||
v3.UserAgent = r.URL.Query().Get("ua")
|
||||
} else {
|
||||
v3.UserAgent = r.UserAgent()
|
||||
}
|
||||
|
||||
// An override value for the Accept-Language HTTP header field. This value is used to detect the visitor's country if GeoIP is not enabled.
|
||||
if r.URL.Query().Get("lang") != "" {
|
||||
v3.Language = r.URL.Query().Get("lang")
|
||||
} else {
|
||||
v3.Language = r.Header.Get("Accept-Language")
|
||||
}
|
||||
|
||||
// defines the User ID for this request.
|
||||
// User ID is any non empty unique string identifying the user (such as an email address or a username).
|
||||
// To access this value, users must be logged-in in your system so you can fetch this user ID from your system, and pass it to Piwik.
|
||||
// The User ID appears in the visitor log, the Visitor profile, and you can Segment reports for one or several User ID (userId segment).
|
||||
// When specified, the User ID will be "enforced".
|
||||
// This means that if there is no recent visit with this User ID, a new one will be created.
|
||||
// If a visit is found in the last 30 minutes with your specified User ID, then the new action will be recorded to this existing visit.
|
||||
v3.UserID = r.URL.Query().Get("uid")
|
||||
|
||||
// defines the visitor ID for this request.
|
||||
// You must set this value to exactly a 16 character hexadecimal string (containing only characters 01234567890abcdefABCDEF).
|
||||
// We recommended to set the User ID via uid rather than use this cid
|
||||
v3.CustomUserID = r.URL.Query().Get("cid")
|
||||
|
||||
// If set to 1, will force a new visit to be created for this action. This feature is also available in JavaScript.
|
||||
if r.URL.Query().Get("new_visit") == "1" {
|
||||
v3.NewVisit = true
|
||||
}
|
||||
|
||||
/*
|
||||
// ? scopes?
|
||||
dimension := make(map[string]string)
|
||||
for k, v := range r.URL.Query() {
|
||||
if strings.HasPrefix(k, "dimension") {
|
||||
dimension[strings.TrimPrefix(k, "dimension")] = v
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
Optional Action info (measure Page view, Outlink, Download, Site search)
|
||||
*/
|
||||
|
||||
// Page scope custom variables. This is a JSON encoded string of the custom variable array (see below for an example value).
|
||||
json.Unmarshal([]byte(r.URL.Query().Get("cvar")), v3.PageCustomVars)
|
||||
|
||||
// An external URL the user has opened.
|
||||
// Used for tracking outlink clicks.
|
||||
// We recommend to also set the url parameter to this same value.
|
||||
v3.Link = r.URL.Query().Get("link")
|
||||
|
||||
// URL of a file the user has downloaded.
|
||||
// Used for tracking downloads.
|
||||
// We recommend to also set the url parameter to this same value.
|
||||
v3.Download = r.URL.Query().Get("download")
|
||||
|
||||
// The Site Search keyword.
|
||||
// When specified, the request will not be tracked as a normal pageview but will instead be tracked as a Site Search request.
|
||||
v3.Search = r.URL.Query().Get("search")
|
||||
|
||||
// when search is specified, you can optionally specify a search category with this parameter.
|
||||
v3.SearchCategory = r.URL.Query().Get("search_cat")
|
||||
|
||||
// when search is specified, we also recommend to set the search_count to the number of search results displayed on the results page.
|
||||
// When keywords are tracked with &search_count=0 they will appear in the "No Result Search Keyword" report.
|
||||
v3.SearchCount = r.URL.Query().Get("search_count")
|
||||
|
||||
// Accepts a six character unique ID that identifies which actions were performed on a specific page view.
|
||||
// When a page was viewed, all following tracking requests (such as events) during that page view should use the same pageview ID.
|
||||
// Once another page was viewed a new unique ID should be generated.
|
||||
// Use [0-9a-Z] as possible characters for the unique ID.
|
||||
v3.PageViewID = r.URL.Query().Get("pv_id")
|
||||
|
||||
// If specified, the tracking request will trigger a conversion for the goal of the website being tracked with this ID.
|
||||
v3.GoalID = r.URL.Query().Get("idgoal")
|
||||
|
||||
// A monetary value that was generated as revenue by this goal conversion.
|
||||
// Only used if idgoal is specified in the request.
|
||||
v3.Revenue = r.URL.Query().Get("revenue")
|
||||
|
||||
// The amount of time it took the server to generate this action, in milliseconds.
|
||||
// This value is used to process the Page speed report Avg. generation time column in the Page URL and Page Title reports,
|
||||
// as well as a site wide running average of the speed of your server.
|
||||
// Note: when using the JavaScript tracker this value is set to the time for server to generate response + the time for client to download response.
|
||||
v3.GenerationTime = r.URL.Query().Get("gt_ms")
|
||||
|
||||
// The charset of the page being tracked.
|
||||
// Specify the charset if the data you send to Piwik is encoded in a different character set than the default utf-8.
|
||||
v3.Characterset = r.URL.Query().Get("cs")
|
||||
|
||||
/*
|
||||
Optional Event Tracking info
|
||||
*/
|
||||
|
||||
// The event category. Must not be empty. (eg. Videos, Music, Games...)
|
||||
v3.EventCategory = r.URL.Query().Get("e_c")
|
||||
|
||||
// The event action. Must not be empty. (eg. Play, Pause, Duration, Add Playlist, Downloaded, Clicked...)
|
||||
v3.EventAction = r.URL.Query().Get("e_a")
|
||||
|
||||
// The event name. (eg. a Movie name, or Song name, or File name...)
|
||||
v3.EventName = r.URL.Query().Get("e_n")
|
||||
|
||||
// The event value. Must be a float or integer value (numeric), not a string.
|
||||
v3.EventValue = r.URL.Query().Get("e_v")
|
||||
|
||||
/*
|
||||
Optional Content Tracking info
|
||||
*/
|
||||
|
||||
// The name of the content. For instance 'Ad Foo Bar'
|
||||
v3.ContentName = r.URL.Query().Get("c_n")
|
||||
// The actual content piece. For instance the path to an image, video, audio, any text
|
||||
v3.ContentPiece = r.URL.Query().Get("c_p")
|
||||
// The target of the content. For instance the URL of a landing page
|
||||
v3.ContentTarget = r.URL.Query().Get("c_t")
|
||||
// The name of the interaction with the content. For instance a 'click'
|
||||
v3.ContentInteraction = r.URL.Query().Get("c_i")
|
||||
|
||||
// Optional Ecommerce info
|
||||
// you must set &idgoal=0 in the request to track an ecommerce interaction: cart update or an ecommerce order.
|
||||
if r.URL.Query().Get("idgoal") == "0" {
|
||||
// The unique string identifier for the ecommerce order (required when tracking an ecommerce order)
|
||||
v3.ECommerceID = r.URL.Query().Get("ec_id")
|
||||
|
||||
// Items in the Ecommerce order.
|
||||
// This is a JSON encoded array of items. Each item is an array with the following info in this order: item sku, item name, item category, item price, item quantity.
|
||||
json.Unmarshal([]byte(r.URL.Query().Get("ec_items")), v3.ECommerceItems)
|
||||
|
||||
// The grand total for the ecommerce order (required when tracking an ecommerce order)
|
||||
v3.Revenue = r.URL.Query().Get("revenue")
|
||||
|
||||
// The sub total of the order; excludes shipping.
|
||||
v3.ECommerceSubTotal = r.URL.Query().Get("ec_st")
|
||||
|
||||
// Tax Amount of the order
|
||||
v3.ECommerceTax = r.URL.Query().Get("ec_tx")
|
||||
|
||||
// Shipping cost of the Order
|
||||
v3.ECommerceShipping = r.URL.Query().Get("ec_sh")
|
||||
|
||||
// Discount offered
|
||||
v3.ECommerceDiscount = r.URL.Query().Get("ec_dt")
|
||||
|
||||
// The UNIX timestamp of this customer's last ecommerce order.
|
||||
// This value is used to process the "Days since last order" report.
|
||||
v3.ECommerceTime = stringToTime(r.URL.Query().Get("_ects"))
|
||||
}
|
||||
|
||||
/*
|
||||
Other parameters (require authentication via token_auth)
|
||||
*/
|
||||
|
||||
// 32 character authorization key used to authenticate the API request.
|
||||
v3.TokenAuth = r.URL.Query().Get("token_auth")
|
||||
|
||||
// Override value for the visitor IP (both IPv4 and IPv6 notations supported).
|
||||
v3.CustomIP = r.URL.Query().Get("cip")
|
||||
|
||||
// Override for the datetime of the request (normally the current time is used).
|
||||
// This can be used to record visits and page views in the past.
|
||||
// The expected format is either a datetime such as: 2011-04-05 00:11:42 (remember to URL encode the value!), or a valid UNIX timestamp such as 1301919102.
|
||||
// The datetime must be sent in UTC timezone.
|
||||
// Note: if you record data in the past, you will need to force Piwik to re-process reports for the past dates.
|
||||
// If you set cdt to a datetime older than 24 hours then token_auth must be set.
|
||||
// If you set cdt with a datetime in the last 24 hours then you don't need to pass token_auth.
|
||||
v3.CustomDateTime = r.URL.Query().Get("cdt")
|
||||
|
||||
// An override value for the country. Should be set to the two letter country code of the visitor (lowercase), eg fr, de, us.
|
||||
v3.CustomCountry = r.URL.Query().Get("country")
|
||||
|
||||
// An override value for the region. Should be set to the two letter region code as defined by MaxMind's GeoIP databases. See here for a list of them for every country (the region codes are located in the second column, to the left of the region name and to the right of the country code).
|
||||
v3.CustomRegion = r.URL.Query().Get("region")
|
||||
|
||||
// An override value for the city. The name of the city the visitor is located in, eg, Tokyo.
|
||||
v3.CustomCity = r.URL.Query().Get("city")
|
||||
|
||||
// An override value for the visitor's latitude, eg 22.456.
|
||||
v3.CustomLatitude = r.URL.Query().Get("lat")
|
||||
|
||||
// An override value for the visitor's longitude, eg 22.456.
|
||||
v3.CustomLongitude = r.URL.Query().Get("long")
|
||||
|
||||
/*
|
||||
Media Analytics parameters
|
||||
https://developer.piwik.org/guides/media-analytics/custom-player#media-analytics-http-tracking-api-reference
|
||||
*/
|
||||
|
||||
// A unique id that is always the same while playing a media. As soon as the played media changes (new video or audio started), this ID has to change.
|
||||
v3.MediaID = r.URL.Query().Get("ma_id")
|
||||
|
||||
// The name / title of the media.
|
||||
v3.MediaTitle = r.URL.Query().Get("ma_ti")
|
||||
|
||||
// The URL of the media resource.
|
||||
v3.MediaResource = r.URL.Query().Get("ma_re")
|
||||
|
||||
// video or audio depending on the type of the media.
|
||||
v3.MediaType = r.URL.Query().Get("ma_mt")
|
||||
|
||||
// The name of the media player, for example html5.
|
||||
v3.MediaPlayerName = r.URL.Query().Get("ma_pn")
|
||||
|
||||
// The time in seconds for how long a user has been playing this media.
|
||||
// This number should typically increase when you send a media tracking request.
|
||||
// It should be 0 if the media was only visible/impressed but not played.
|
||||
// Do not increase this number when a media is paused.
|
||||
v3.MediaSecondsPlayingTime = r.URL.Query().Get("ma_st")
|
||||
|
||||
// The duration (the length) of the media in seconds. For example if a video is 90 seconds long, the value should be 90.
|
||||
v3.MediaLength = r.URL.Query().Get("ma_le")
|
||||
|
||||
// The progress / current position within the media. Defines basically at which position within the total length the user is currently playing.
|
||||
v3.MediaProgress = r.URL.Query().Get("ma_ps")
|
||||
|
||||
// Defines after how many seconds the user has started playing this media.
|
||||
// For example a user might have seen the poster of the video for 30 seconds before a user actually pressed the play button.
|
||||
v3.MediaTimeUntilPlay = r.URL.Query().Get("ma_ttp")
|
||||
|
||||
// The resolution width of the media in pixels. Only recommended to be set for videos.
|
||||
v3.MediaWidth = r.URL.Query().Get("ma_w")
|
||||
|
||||
// The resolution height of the media in pixels. Only recommended to be set for videos.
|
||||
v3.MediaHeight = r.URL.Query().Get("ma_h")
|
||||
|
||||
// Should be 0 or 1 and defines whether the media is currently viewed in full screen. Only recommended to be set for videos.
|
||||
switch r.URL.Query().Get("ma_fs") {
|
||||
case "0":
|
||||
v3.MediaFullscreen = false
|
||||
case "1":
|
||||
v3.MediaFullscreen = true
|
||||
default:
|
||||
v3.MediaFullscreen = false
|
||||
}
|
||||
|
||||
// If set to 0 (send_image=0) Piwik will respond with a HTTP 204 response code instead of a GIF image.
|
||||
// This improves performance and can fix errors if images are not allowed to be obtained directly (eg Chrome Apps).
|
||||
// Available since Piwik 2.10.0
|
||||
v3.SendImage = r.URL.Query().Get("send_image")
|
||||
|
||||
return v3
|
||||
|
||||
/*
|
||||
r.URL.Query().Get("") //
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
func stringToTime(s string) time.Time {
|
||||
i, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
return time.Time{}
|
||||
}
|
||||
return time.Unix(i, 0)
|
||||
}
|
||||
|
||||
func atoi(a string) int {
|
||||
i, err := strconv.Atoi(a)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return i
|
||||
}
|
98
piwik/storage.go
Normal file
98
piwik/storage.go
Normal file
@ -0,0 +1,98 @@
|
||||
package piwik
|
||||
|
||||
import "time"
|
||||
|
||||
type SiteStorageInterface interface {
|
||||
Add(site *Site) error
|
||||
Remove(site *Site) error
|
||||
Update(site *Site) error
|
||||
List() ([]*Site, error)
|
||||
FindId(id string) (*Site, error)
|
||||
Find(query map[string]interface{}) (*Site, error)
|
||||
FindAll(query map[string]interface{}) ([]*Site, error)
|
||||
}
|
||||
|
||||
type VisitStorageInterface interface {
|
||||
Add(visit *Visit) error
|
||||
Find(query map[string]interface{}) (*Visit, error)
|
||||
FindAll(query map[string]interface{}) ([]*Visit, error)
|
||||
}
|
||||
|
||||
type Site struct {
|
||||
ID string `bson:"_id" json:"id"`
|
||||
Name string `bson:"name" json:"name"`
|
||||
Domain string `bson:"domain" json:"domain"`
|
||||
}
|
||||
|
||||
type Visit struct {
|
||||
ID string `bson:"_id" json:"id"`
|
||||
SiteID string `bson:"site_id" json:"site_id"` //idsite
|
||||
URL string `bson:"url" json:"url"` //url
|
||||
ActionName string `bson:"action_name,omitempty" json:"action_name,omitempty"` //action_anem
|
||||
VisitorID string `bson:"visitor_id,omitempty" json:"visitor_id,omitempty"` //_id
|
||||
Referrer string `bson:"referrer,omitempty" json:"referrer,omitempty"` //urlref
|
||||
CustomVars map[string]interface{} `bson:"custom_vars,omitempty" json:"custom_vars,omitempty"` //_cvar
|
||||
VisitsCount string `bson:"visits_count,omitempty" json:"visits_count,omitempty"` //_idvc
|
||||
ViewTime time.Time `bson:"view_time,omitempty" json:"view_time,omitempty"` //_viewts
|
||||
VisitorFirstVisitTime time.Time `bson:"visitor_first_visit_time,omitempty" json:"visitor_first_visit_time,omitempty"` //_idts
|
||||
CampaignName string `bson:"campaign_name,omitempty" json:"campaign_name,omitempty"` //_rcn
|
||||
CampaignKeyword string `bson:"campaign_keyword,omitempty" json:"campaign_keyword,omitempty"` //_rck
|
||||
Resolution string `bson:"resolution,omitempty" json:"resolution,omitempty"` //res
|
||||
LocalHour string `bson:"local_hour,omitempty" json:"local_hour,omitempty"` //h
|
||||
LocalMinute string `bson:"local_minute,omitempty" json:"local_minute,omitempty"` //m
|
||||
LocalSeconds string `bson:"local_seconds,omitempty" json:"local_seconds,omitempty"` //s
|
||||
LocalTimeUTC time.Time `bson:"local_time_utc,omitempty" json:"local_time_utc,omitempty"`
|
||||
Plugins *Plugins `bson:"plugins" json:"plugins"`
|
||||
SupportsCookies bool `bson:"supports_cookies,omitempty" json:"supports_cookies,omitempty"` //cookie
|
||||
UserAgent string `bson:"user_agent,omitempty" json:"user_agent,omitempty"` //ua
|
||||
Language string `bson:"language,omitempty" json:"language,omitempty"` //lang
|
||||
UserID string `bson:"user_id,omitempty" json:"user_id,omitempty"` //uid
|
||||
CustomUserID string `bson:"custom_user_id,omitempty" json:"custom_user_id,omitempty"` //cid
|
||||
NewVisit bool `bson:"new_visit,omitempty" json:"new_visit,omitempty"` //new_visit
|
||||
PageCustomVars map[string]interface{} `bson:"page_custom_vars,omitempty" json:"page_custom_vars,omitempty"` //cvar
|
||||
Link string `bson:"link,omitempty" json:"link,omitempty"` //link
|
||||
Download string `bson:"download,omitempty" json:"download,omitempty"` //download
|
||||
Search string `bson:"search,omitempty" json:"search,omitempty"` //search
|
||||
SearchCategory string `bson:"search_category,omitempty" json:"search_category,omitempty"` //search_cat
|
||||
SearchCount string `bson:"search_count,omitempty" json:"search_count,omitempty"` //search_count
|
||||
PageViewID string `bson:"page_view_id,omitempty" json:"page_view_id,omitempty"` //pv_id
|
||||
GoalID string `bson:"goal_id,omitempty" json:"goal_id,omitempty"` //idgoal
|
||||
Revenue string `bson:"revenue,omitempty" json:"revenue,omitempty"` //revenue
|
||||
GenerationTime string `bson:"generation_time,omitempty" json:"generation_time,omitempty"` //gt_ms
|
||||
Characterset string `bson:"characterset,omitempty" json:"characterset,omitempty"` //cs
|
||||
EventCategory string `bson:"event_category,omitempty" json:"event_category,omitempty"` //e_c
|
||||
EventAction string `bson:"event_action,omitempty" json:"event_action,omitempty"` //e_a
|
||||
EventName string `bson:"event_name,omitempty" json:"event_name,omitempty"` //e_n
|
||||
EventValue string `bson:"event_value,omitempty" json:"event_value,omitempty"` //e_v
|
||||
ContentName string `bson:"content_name,omitempty" json:"content_name,omitempty"` //c_n
|
||||
ContentPiece string `bson:"content_piece,omitempty" json:"content_piece,omitempty"` //c_p
|
||||
ContentTarget string `bson:"content_target,omitempty" json:"content_target,omitempty"` //c_t
|
||||
ContentInteraction string `bson:"content_interaction,omitempty" json:"content_interaction,omitempty"` //c_i
|
||||
ECommerceID string `bson:"ecommerce_id,omitempty" json:"ecommerce_id,omitempty"` // ec_id
|
||||
ECommerceItems [][]string `bson:"ecommerce_items,omitempty" json:"ecommerce_items,omitempty"` // ec_items
|
||||
ECommerceSubTotal string `bson:"ecommerce_sub_total,omitempty" json:"ecommerce_sub_total,omitempty"` // ec_st
|
||||
ECommerceTax string `bson:"ecommerce_tax,omitempty" json:"ecommerce_tax,omitempty"` // ec_tx
|
||||
ECommerceShipping string `bson:"ecommerce_shipping,omitempty" json:"ecommerce_shipping,omitempty"` // ec_sh
|
||||
ECommerceDiscount string `bson:"ecommerce_discount,omitempty" json:"ecommerce_discount,omitempty"` // ec_dt
|
||||
ECommerceTime time.Time `bson:"ecommerce_time,omitempty" json:"ecommerce_time,omitempty"` // ec_ts
|
||||
TokenAuth string `bson:"token_auth,omitempty" json:"token_auth,omitempty"` //token_auth
|
||||
CustomIP string `bson:"custom_ip,omitempty" json:"custom_ip,omitempty"` //cip
|
||||
CustomDateTime string `bson:"custom_date_time,omitempty" json:"custom_date_time,omitempty"` //cdt
|
||||
CustomCountry string `bson:"custom_country,omitempty" json:"custom_country,omitempty"` //country
|
||||
CustomRegion string `bson:"custom_region,omitempty" json:"custom_region,omitempty"` //region
|
||||
CustomCity string `bson:"custom_city,omitempty" json:"custom_city,omitempty"` //city
|
||||
CustomLatitude string `bson:"custom_latitude,omitempty" json:"custom_latitude,omitempty"` //lat
|
||||
CustomLongitude string `bson:"custom_longitude,omitempty" json:"custom_longitude,omitempty"` //long
|
||||
MediaID string `bson:"media_id,omitempty" json:"media_id,omitempty"` // ma_id
|
||||
MediaTitle string `bson:"media_title,omitempty" json:"media_title,omitempty"` // ma_ti
|
||||
MediaResource string `bson:"media_resource,omitempty" json:"media_resource,omitempty"` // ma_re
|
||||
MediaType string `bson:"media_type,omitempty" json:"media_type,omitempty"` // ma_mt
|
||||
MediaPlayerName string `bson:"media_player_name,omitempty" json:"media_player_name,omitempty"` // ma_pn
|
||||
MediaSecondsPlayingTime string `bson:"media_seconds_playing_time,omitempty" json:"media_seconds_playing_time,omitempty"` // ma_st
|
||||
MediaLength string `bson:"media_length,omitempty" json:"media_length,omitempty"` // ma_le
|
||||
MediaProgress string `bson:"media_progress,omitempty" json:"media_progress,omitempty"` // ma_ps
|
||||
MediaTimeUntilPlay string `bson:"media_time_until_play,omitempty" json:"media_time_until_play,omitempty"` // ma_ttp
|
||||
MediaWidth string `bson:"media_width,omitempty" json:"media_width,omitempty"` // ma_w
|
||||
MediaHeight string `bson:"media_height,omitempty" json:"media_height,omitempty"` // ma_h
|
||||
MediaFullscreen bool `bson:"media_fullscreen,omitempty" json:"media_fullscreen,omitempty"` // ma_fs
|
||||
}
|
Loading…
Reference in New Issue
Block a user