diff --git a/PiwikTracker.xcodeproj/project.pbxproj b/PiwikTracker.xcodeproj/project.pbxproj index fad596d5..81f74cd9 100644 --- a/PiwikTracker.xcodeproj/project.pbxproj +++ b/PiwikTracker.xcodeproj/project.pbxproj @@ -33,6 +33,7 @@ 1FCFF0241F82C7A50038BC17 /* CustomDimension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDC917B1F1A64BB0046F506 /* CustomDimension.swift */; }; 1FDC917F1F1A65150046F506 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDC917D1F1A65150046F506 /* Application.swift */; }; 1FDC91801F1A65150046F506 /* Device.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FDC917E1F1A65150046F506 /* Device.swift */; }; + 32033A4E201C815D007CB511 /* CustomVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32033A4D201C815D007CB511 /* CustomVariable.swift */; }; 82A551CEC50ABB2EAD50FC4E /* Pods_PiwikTrackerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68F0C25DEF98C13D32CC46DD /* Pods_PiwikTrackerTests.framework */; }; /* End PBXBuildFile section */ @@ -76,6 +77,7 @@ 1FDC917B1F1A64BB0046F506 /* CustomDimension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomDimension.swift; sourceTree = ""; }; 1FDC917D1F1A65150046F506 /* Application.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; 1FDC917E1F1A65150046F506 /* Device.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Device.swift; sourceTree = ""; }; + 32033A4D201C815D007CB511 /* CustomVariable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomVariable.swift; sourceTree = ""; }; 68F0C25DEF98C13D32CC46DD /* Pods_PiwikTrackerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PiwikTrackerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8F688B0F18F298B5E61552AC /* Pods-PiwikTrackerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PiwikTrackerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PiwikTrackerTests/Pods-PiwikTrackerTests.release.xcconfig"; sourceTree = ""; }; FD284F50B998823EAFB0CEE9 /* Pods-PiwikTrackerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PiwikTrackerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PiwikTrackerTests/Pods-PiwikTrackerTests.debug.xcconfig"; sourceTree = ""; }; @@ -160,6 +162,7 @@ 1F6F0CD61E61E35A008170FC /* PiwikTracker.swift */, 1F6F0CE01E61E4F3008170FC /* URLSessionDispatcher.swift */, 1FDC917B1F1A64BB0046F506 /* CustomDimension.swift */, + 32033A4D201C815D007CB511 /* CustomVariable.swift */, 1F38EBF71EE568D10021FBF8 /* Logger.swift */, 1FDC917D1F1A65150046F506 /* Application.swift */, 1FDC917E1F1A65150046F506 /* Device.swift */, @@ -383,6 +386,7 @@ 1F0A15D01E6335E900FEAE72 /* Session.swift in Sources */, 1F092C1A1E26B44500394B30 /* Dispatcher.swift in Sources */, 1F38EBF81EE568D10021FBF8 /* Logger.swift in Sources */, + 32033A4E201C815D007CB511 /* CustomVariable.swift in Sources */, 1FCFF0241F82C7A50038BC17 /* CustomDimension.swift in Sources */, 1F7C667F1F8C096F0066CC64 /* MainThread.swift in Sources */, 1F80856F1E6B4B9800A61AAF /* Locale+HttpAcceptLanguage.swift in Sources */, diff --git a/PiwikTracker/CustomVariable.swift b/PiwikTracker/CustomVariable.swift new file mode 100644 index 00000000..99dbe516 --- /dev/null +++ b/PiwikTracker/CustomVariable.swift @@ -0,0 +1,15 @@ + +import Foundation + + +/// See Custom Variable documentation here: https://piwik.org/docs/custom-variables/ +public struct CustomVariable { + /// The index of the variable. + let index: UInt + + /// The name of the variable. + let name: String + + /// The value of the variable. + let value: String +} diff --git a/PiwikTracker/Event.swift b/PiwikTracker/Event.swift index ec752f9a..2650b0c7 100644 --- a/PiwikTracker/Event.swift +++ b/PiwikTracker/Event.swift @@ -55,8 +55,9 @@ public struct Event { /// api-key: urlref let referer: URL? let screenResolution : CGSize = Device.makeCurrentDevice().screenSize + /// api-key: _cvar - //let customVariables: [CustomVariable] + let customVariables: [CustomVariable] /// Event tracking /// https://piwik.org/docs/event-tracking/ @@ -71,7 +72,7 @@ public struct Event { } extension Event { - public init(tracker: PiwikTracker, action: [String], url: URL? = nil, referer: URL? = nil, eventCategory: String? = nil, eventAction: String? = nil, eventName: String? = nil, eventValue: Float? = nil, customTrackingParameters: [String:String] = [:], dimensions: [CustomDimension] = []) { + public init(tracker: PiwikTracker, action: [String], url: URL? = nil, referer: URL? = nil, eventCategory: String? = nil, eventAction: String? = nil, eventName: String? = nil, eventValue: Float? = nil, customTrackingParameters: [String:String] = [:], dimensions: [CustomDimension] = [], variables: [CustomVariable] = []) { self.siteId = tracker.siteId self.uuid = NSUUID() self.visitor = tracker.visitor @@ -88,5 +89,6 @@ extension Event { self.eventValue = eventValue self.dimensions = tracker.dimensions + dimensions self.customTrackingParameters = customTrackingParameters + self.customVariables = tracker.customVariables + variables } } diff --git a/PiwikTracker/EventSerializer.swift b/PiwikTracker/EventSerializer.swift index a755e3a8..fbe9cc5a 100644 --- a/PiwikTracker/EventSerializer.swift +++ b/PiwikTracker/EventSerializer.swift @@ -24,6 +24,12 @@ final class EventSerializer { } fileprivate extension Event { + + private func customVariableParameterValue() -> String { + let customVariableParameterValue: [String] = customVariables.map { "\"\($0.index)\":[\"\($0.name)\",\"\($0.value)\"]" } + return "{\(customVariableParameterValue.joined(separator: ","))}" + } + var queryItems: [URLQueryItem] { get { let items = [ @@ -57,10 +63,12 @@ fileprivate extension Event { URLQueryItem(name: "e_v", value: eventValue != nil ? "\(eventValue!)" : nil), ].filter { $0.value != nil } - + let dimensionItems = dimensions.map { URLQueryItem(name: "dimension\($0.index)", value: $0.value) } let customItems = customTrackingParameters.map { return URLQueryItem(name: $0.key, value: $0.value) } - return items + dimensionItems + customItems + let customVariableItems = customVariables.count > 0 ? [URLQueryItem(name: "_cvar", value: customVariableParameterValue())] : [] + + return items + dimensionItems + customItems + customVariableItems } } } diff --git a/PiwikTracker/PiwikTracker.swift b/PiwikTracker/PiwikTracker.swift index 42261e61..58a7d6a7 100644 --- a/PiwikTracker/PiwikTracker.swift +++ b/PiwikTracker/PiwikTracker.swift @@ -36,6 +36,7 @@ final public class PiwikTracker: NSObject { internal var dimensions: [CustomDimension] = [] + internal var customVariables: [CustomVariable] = [] /// This logger is used to perform logging of all sorts of piwik related information. /// Per default it is a `DefaultLogger` with a `minLevel` of `LogLevel.warning`. You can @@ -153,7 +154,7 @@ final public class PiwikTracker: NSObject { // MARK: dispatch timer - public var dispatchInterval: TimeInterval = 30.0 { + @objc public var dispatchInterval: TimeInterval = 30.0 { didSet { startDispatchTimer() } @@ -295,18 +296,56 @@ extension PiwikTracker { dimensions.append(dimension) } + /// Set a permanent custom dimension by value and index. + /// + /// This is a convenience alternative to set(dimension:) and calls the exact same functionality. Also, it is accessible from Objective-C. + /// + /// - Parameter value: The value for the new Custom Dimension + /// - Parameter forIndex: The index of the new Custom Dimension + @objc public func setDimension(_ value: String, forIndex index: Int) { + set(dimension: CustomDimension( index: index, value: value )); + } + /// Removes a previously set custom dimension. /// /// Use this method to remove a dimension that was set using the `set(value: String, forDimension index: Int)` method. /// /// - Parameter index: The index of the dimension. - public func remove(dimensionAtIndex index: Int) { + @objc public func remove(dimensionAtIndex index: Int) { dimensions = dimensions.filter({ dimension in dimension.index != index }) } } + +extension PiwikTracker { + + /// Set a permanent new Custom Variable. + /// + /// - Parameter dimension: The Custom Variable to set + public func set(customVariable: CustomVariable) { + removeCustomVariable(withIndex: customVariable.index) + customVariables.append(customVariable) + } + + /// Set a permanent new Custom Variable. + /// + /// - Parameter name: The index of the new Custom Variable + /// - Parameter name: The name of the new Custom Variable + /// - Parameter value: The value of the new Custom Variable + @objc public func setCustomVariable(withIndex index: UInt, name: String, value: String) { + set(customVariable: CustomVariable(index: index, name: name, value: value)) + } + + /// Remove a previously set Custom Variable. + /// + /// - Parameter index: The index of the Custom Variable. + @objc public func removeCustomVariable(withIndex index: UInt) { + customVariables = customVariables.filter { $0.index != index } + } +} + // Objective-c compatibility extension extension PiwikTracker {