-
Notifications
You must be signed in to change notification settings - Fork 25
/
GATracker.swift
executable file
·189 lines (163 loc) · 5.84 KB
/
GATracker.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//
// AnalyticObject.swift
// TVSwiftMeasurementProtocol
//
// Created by Vincent Lee and Luka Cempre on 11/23/15.
// Copyright © 2015 Analytics Pros. All rights reserved.
//
import Foundation
private var _analyticsTracker: GATracker!
class GATracker {
/*
Define properties
@tid = Google Analytics property id
@cid = Google Analytics client id
@appName = Application Name
@appVersion = Application Version
@MPVersion = Measurement Protocol version
@ua = User Agent string
*/
private var tid : String
var cid: String
var appName : String
var appVersion : String
var MPVersion : String
var ua : String
var ul : String
//Set up singleton object for the tracker
class func setup(tid: String) -> GATracker {
DispatchQueue.once {
_analyticsTracker = GATracker(tid: tid)
}
return _analyticsTracker
}
class var sharedInstance: GATracker! {
if _analyticsTracker == nil {
#if DEBUG
print("Analytics Tracker not set up")
#endif
}
return _analyticsTracker
}
init(tid: String) {
/*
Initialize Tracker with Property Id
Set up all attributes
*/
#if DEBUG
print("Google Analytics Tracker Initialized")
#endif
self.tid = tid
self.appName = Bundle.main.infoDictionary!["CFBundleName"] as! String
let nsObject: AnyObject? = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as AnyObject
self.appVersion = nsObject as! String
self.ua = "Mozilla/5.0 (Apple TV; CPU iPhone OS 9_0 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13T534YI"
self.MPVersion = "1"
let defaults = UserDefaults.standard
if let cid = defaults.string(forKey: "cid") {
self.cid = cid
}
else {
self.cid = NSUUID().uuidString
defaults.set(self.cid, forKey: "cid")
}
let language = NSLocale.preferredLanguages.first
if (language?.count)! > 0 {
self.ul = language!
} else {
self.ul = "(not set)"
}
}
func send(type: String, params: Dictionary<String, String>) {
/*
Generic hit sender to Measurement Protocol
Consists out of hit type and a dictionary of other parameters
*/
let endpoint = "https://www.google-analytics.com/collect?"
var parameters = "v=" + self.MPVersion + "&an=" + self.appName + "&tid=" + self.tid + "&av=" + self.appVersion + "&cid=" + self.cid + "&t=" + type + "&ua=" + self.ua + "&ul=" + self.ul
for (key, value) in params {
parameters += "&" + key + "=" + value
}
//Encoding all the parameters
if let paramEndcode = parameters.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)
{
let urlString = endpoint + paramEndcode;
let url = NSURL(string: urlString);
#if DEBUG
print(urlString)
#endif
let task = URLSession.shared.dataTask(with: url! as URL) { (data, response, error) -> Void in
if let httpReponse = response as? HTTPURLResponse {
let statusCode = httpReponse.statusCode
#if DEBUG
print(statusCode)
#endif
}
else {
if (error != nil) {
#if DEBUG
print(error!.localizedDescription)
#endif
}
}
}
task.resume()
}
}
func screenView(screenName: String, customParameters: Dictionary<String, String>?) {
/*
A screenview hit, use screenname
*/
var params = ["cd" : screenName]
if (customParameters != nil) {
for (key, value) in customParameters! {
params.updateValue(value, forKey: key)
}
}
self.send(type: "screenview", params: params)
}
func event(category: String, action: String, label: String?, customParameters: Dictionary<String, String>?) {
/*
An event hit with category, action, label
*/
//event parameters category, action and label
var params = ["ec" : category, "ea" : action, "el" : label ?? ""]
if (customParameters != nil) {
for (key, value) in customParameters! {
params.updateValue(value, forKey: key)
}
}
self.send(type: "event", params: params)
}
func exception(description: String, isFatal:Bool, customParameters: Dictionary<String, String>?) {
/*
An exception hit with exception description (exd) and "fatality" (Crashed or not) (exf)
*/
var fatal="0";
if (isFatal){
fatal = "1";
}
var params = ["exd":description, "exf":fatal]
if (customParameters != nil) {
for (key, value) in customParameters! {
params.updateValue(value, forKey: key)
}
}
self.send(type: "exception", params: params)
}
}
public extension DispatchQueue {
static var token = [String]()
class func once(file: String = #file, line: Int = #line, handler:()->Void) {
once(token: "\(file)_\(line)", handler: handler)
}
class func once(token: String, handler:()->Void) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
if DispatchQueue.token.contains(token) {
return
}
DispatchQueue.token.append(token)
handler()
}
}