Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

track implementation and each launch #541

Merged
merged 13 commits into from
May 5, 2022
12 changes: 12 additions & 0 deletions Sources/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ struct BundleConstants {
static let ID = "com.mixpanel.Mixpanel"
}

struct InternalKeys {
static let mpDebugTrackedKey = "mpDebugTrackedKey"
static let mpDebugInitCountKey = "mpDebugInitCountKey"
static let mpSurveyShownDateKey = "mpSurveyShownDateKey"
static let mpDebugImplementedKey = "mpDebugImplementedKey"
static let mpDebugIdentifiedKey = "mpDebugIdentifiedKey"
static let mpDebugAliasedKey = "mpDebugAliasedKey"
static let mpDebugUsedPeopleKey = "mpDebugUsedPeopleKey"
static let mpSurveyShownCountKey = "mpSurveyShownCountKey"
}


#if !os(OSX) && !os(watchOS)
extension UIDevice {
var iPhoneX: Bool {
Expand Down
84 changes: 63 additions & 21 deletions Sources/Mixpanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ open class Mixpanel {
superProperties: Properties? = nil,
serverURL: String? = nil) -> MixpanelInstance {
#if DEBUG
didDebugInit(distinctId: apiToken, properties: superProperties ?? [:])
didDebugInit(
distinctId: apiToken,
libName: superProperties?.get(key: "mp_lib", defaultValue: nil),
libVersion: superProperties?.get(key: "$lib_version", defaultValue: nil)
)
#endif
return MixpanelManager.sharedInstance.initialize(token: apiToken,
flushInterval: flushInterval,
Expand Down Expand Up @@ -90,7 +94,11 @@ open class Mixpanel {
superProperties: Properties? = nil,
serverURL: String? = nil) -> MixpanelInstance {
#if DEBUG
didDebugInit(distinctId: apiToken, properties: superProperties ?? [:])
didDebugInit(
distinctId: apiToken,
libName: superProperties?.get(key: "mp_lib", defaultValue: nil),
libVersion: superProperties?.get(key: "$lib_version", defaultValue: nil)
)
#endif
return MixpanelManager.sharedInstance.initialize(token: apiToken,
flushInterval: flushInterval,
Expand Down Expand Up @@ -148,21 +156,27 @@ open class Mixpanel {
MixpanelManager.sharedInstance.removeInstance(name: name)
}

private class func didDebugInit(distinctId: String, properties: Properties = [:]) {
let debugInitCountKey = "MPDebugInitCountKey"
let debugInitCount = UserDefaults.standard.integer(forKey: debugInitCountKey) + 1
var debugProperties: Properties = properties
debugProperties += ["Debug Launch Count": debugInitCount]
Network.sendHttpEvent(eventName: "SDK Debug Launch", apiToken: "metrics-1", distinctId: distinctId, properties: debugProperties)
checkForSurvey(distinctId: distinctId, debugInitCount: debugInitCount, properties: properties)
UserDefaults.standard.set(debugInitCount, forKey: debugInitCountKey)
UserDefaults.standard.synchronize()
private class func didDebugInit(distinctId: String, libName: String?, libVersion: String?) {
if distinctId.count == 32 {
let debugInitCount = UserDefaults.standard.integer(forKey: InternalKeys.mpDebugInitCountKey) + 1
var properties: Properties = ["Debug Launch Count": debugInitCount]
if let libName = libName {
properties["mp_lib"] = libName
}
if let libVersion = libVersion {
properties["$lib_version"] = libVersion
}
Network.sendHttpEvent(eventName: "SDK Debug Launch", apiToken: "metrics-1", distinctId: distinctId, properties: properties) { (_) in }
checkForSurvey(distinctId: distinctId, properties: properties)
checkIfImplemented(distinctId: distinctId, properties: properties)
UserDefaults.standard.set(debugInitCount, forKey: InternalKeys.mpDebugInitCountKey)
UserDefaults.standard.synchronize()
}
}

private class func checkForSurvey(distinctId: String, debugInitCount: Int, properties: Properties = [:]) {
let surveyShownCountKey = "MPSurveyShownCountKey"
var surveyShownCount = UserDefaults.standard.integer(forKey: surveyShownCountKey)
if (debugInitCount == 10 || debugInitCount == 20 || debugInitCount == 30) {
private class func checkForSurvey(distinctId: String, properties: Properties) {
let surveyShownDate = UserDefaults.standard.object(forKey: InternalKeys.mpSurveyShownDateKey) as? Date ?? Date.distantPast
if (surveyShownDate.timeIntervalSinceNow < -86400) {
let waveHand = UnicodeScalar(0x1f44b) ?? "*"
let thumbsUp = UnicodeScalar(0x1f44d) ?? "*"
let thumbsDown = UnicodeScalar(0x1f44e) ?? "*"
Expand All @@ -171,12 +185,40 @@ open class Mixpanel {
Hi, Zihe & Jared here, please give feedback or tell us about the Mixpanel developer experience!
open -> https://www.mixpanel.com/devnps \(thumbsUp)\(thumbsDown)
""")
print(Array(repeating: "\(waveHand)", count: 10).joined(separator: ""))
surveyShownCount += 1
UserDefaults.standard.set(surveyShownCount, forKey: surveyShownCountKey)
var debugProperties: Properties = properties
debugProperties += ["Survey Shown Count": surveyShownCount]
Network.sendHttpEvent(eventName: "Dev NPS Survey Logged", apiToken: "metrics-1", distinctId: distinctId, properties: debugProperties)
UserDefaults.standard.set(Date(), forKey: InternalKeys.mpSurveyShownDateKey)
let surveyShownCount = UserDefaults.standard.integer(forKey: InternalKeys.mpSurveyShownCountKey) + 1
UserDefaults.standard.set(surveyShownCount, forKey: InternalKeys.mpSurveyShownCountKey)
let trackProps = properties.merging(["Survey Shown Count": surveyShownCount]) {(_,new) in new}
Network.sendHttpEvent(eventName: "Dev NPS Survey Logged", apiToken: "metrics-1", distinctId: distinctId, properties: trackProps) { (_) in }
}
}

private class func checkIfImplemented(distinctId: String, properties: Properties) {
let hasImplemented: Bool = UserDefaults.standard.bool(forKey: InternalKeys.mpDebugImplementedKey)
if !hasImplemented {
var completed = 0
let hasTracked: Bool = UserDefaults.standard.bool(forKey: InternalKeys.mpDebugTrackedKey)
completed += hasTracked ? 1 : 0
let hasIdentified: Bool = UserDefaults.standard.bool(forKey: InternalKeys.mpDebugIdentifiedKey)
completed += hasIdentified ? 1 : 0
let hasAliased: Bool = UserDefaults.standard.bool(forKey: InternalKeys.mpDebugAliasedKey)
completed += hasAliased ? 1 : 0
let hasUsedPeople: Bool = UserDefaults.standard.bool(forKey: InternalKeys.mpDebugUsedPeopleKey)
completed += hasUsedPeople ? 1 : 0
if (completed >= 3) {
let trackProps = properties.merging([
"Tracked": hasTracked,
"Identified": hasIdentified,
"Aliased": hasAliased,
"Used People": hasUsedPeople,
]) {(_,new) in new}
Network.sendHttpEvent(
eventName: "SDK Implemented",
apiToken: "metrics-1",
distinctId: distinctId,
properties: trackProps) { (_) in }
UserDefaults.standard.set(true, forKey: InternalKeys.mpDebugImplementedKey)
}
}
}
}
Expand Down
17 changes: 9 additions & 8 deletions Sources/MixpanelInstance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -152,19 +152,16 @@ open class MixpanelInstance: CustomDebugStringConvertible, FlushDelegate, AEDele
Logger.enableLevel(.warning)
Logger.enableLevel(.error)
Logger.info(message: "Logging Enabled")
#if DEBUG
Network.sendHttpEvent(eventName: "Toggle SDK Logging", apiToken: "metrics-1", distinctId: apiToken, properties: ["Logging Enabled": true])
#endif
} else {
Logger.info(message: "Logging Disabled")
Logger.disableLevel(.debug)
Logger.disableLevel(.info)
Logger.disableLevel(.warning)
Logger.disableLevel(.error)
}
#if DEBUG
Network.sendHttpEvent(eventName: "Toggle SDK Logging", apiToken: "metrics-1", distinctId: apiToken, properties: ["Logging Enabled": false])
Network.sendHttpEvent(eventName: "Toggle SDK Logging", apiToken: "metrics-1", distinctId: apiToken, properties: ["Logging Enabled": loggingEnabled])
#endif
}
}
}

Expand Down Expand Up @@ -592,7 +589,9 @@ extension MixpanelInstance {
}
return
}

#if DEBUG
UserDefaults.standard.set(true, forKey: InternalKeys.mpDebugIdentifiedKey)
#endif
trackingQueue.async { [weak self, distinctId, usePeople] in
guard let self = self else { return }

Expand Down Expand Up @@ -680,7 +679,9 @@ extension MixpanelInstance {
}
return
}

#if DEBUG
UserDefaults.standard.set(true, forKey: InternalKeys.mpDebugAliasedKey)
#endif
if alias != distinctId {
trackingQueue.async { [weak self, alias] in
guard let self = self else {
Expand Down Expand Up @@ -820,7 +821,7 @@ extension MixpanelInstance {
let defaultsKey = "trackedKey"
if !UserDefaults.standard.bool(forKey: defaultsKey) {
trackingQueue.async { [apiToken, defaultsKey] in
Network.sendHttpEvent(eventName: "Integration", apiToken: "85053bf24bba75239b16a601d9387e17", distinctId: apiToken) { [defaultsKey] (success) in
Network.sendHttpEvent(eventName: "Integration", apiToken: "85053bf24bba75239b16a601d9387e17", distinctId: apiToken, updatePeople: false) { [defaultsKey] (success) in
if success {
UserDefaults.standard.set(true, forKey: defaultsKey)
UserDefaults.standard.synchronize()
Expand Down
19 changes: 17 additions & 2 deletions Sources/Network.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,14 @@ class Network {

class func sendHttpEvent(eventName: String, apiToken: String, distinctId: String,
properties: Properties = [:],
updatePeople: Bool = true,
completion: ((Bool) -> Void)? = nil) {
let trackProperties = properties.merging(["token": apiToken,
"mp_lib": properties["mp_lib"] ?? "swift",
"mp_lib": "swift",
"distinct_id": distinctId,
"$lib_version": properties["$lib_version"] ?? AutomaticProperties.libVersion()]) {(current, _) in current }
"$lib_version": AutomaticProperties.libVersion(),
"Project Token": distinctId,
"DevX": true]) {(current, _) in current }
let requestData = JSONHandler.encodeAPIData([["event": eventName, "properties": trackProperties]])

let responseParser: (Data) -> Int? = { data in
Expand Down Expand Up @@ -172,5 +175,17 @@ class Network {
}
)
}
if updatePeople {
let engageData = JSONHandler.encodeAPIData([["$token": apiToken, "$distinct_id": distinctId, "$add": [eventName: 1]]])
if let engageData = engageData {
let engageBody = "ip=1&data=\(engageData)".data(using: String.Encoding.utf8)
let engageResource = Network.buildResource(path: FlushType.people.rawValue,
method: .post,
requestBody: engageBody,
headers: ["Accept-Encoding": "gzip"],
parse: responseParser)
Network.apiRequest(base: BasePath.DefaultMixpanelAPI, resource: engageResource) { _, _, _ in } success: { _, _ in }
}
}
}
}
5 changes: 5 additions & 0 deletions Sources/People.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ open class People {
if mixpanelInstance?.hasOptedOutTracking() ?? false {
return
}
#if DEBUG
if !(properties.keys.first?.hasPrefix("$ae_") ?? true) {
UserDefaults.standard.set(true, forKey: InternalKeys.mpDebugUsedPeopleKey)
}
#endif
let epochMilliseconds = round(Date().timeIntervalSince1970 * 1000)
let ignoreTimeCopy = ignoreTime

Expand Down
6 changes: 5 additions & 1 deletion Sources/Track.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ class Track {
return timedEvents
}
assertPropertyTypes(properties)

#if DEBUG
if !ev.hasPrefix("$") {
UserDefaults.standard.set(true, forKey: InternalKeys.mpDebugTrackedKey)
}
#endif
let epochSeconds = Int(round(epochInterval))
let eventStartTime = timedEvents[ev] as? Double
var p = InternalProperties()
Expand Down