Skip to content

Commit a578954

Browse files
Merge pull request #5 from chazchazchaz/feature/metadata
Feature/metadata
2 parents f0f3332 + cb2a070 commit a578954

File tree

3 files changed

+84
-9
lines changed

3 files changed

+84
-9
lines changed

Sources/SimpleAnalytics/Event.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ internal struct Event: Encodable {
2020
let screen_width: Int?
2121
let screen_height: Int?
2222
let unique: Bool?
23+
var metadata: String?
2324

24-
init(type: EventType, hostname: String, event: String, ua: String? = nil, path: String? = nil, language: String? = nil, timezone: String? = nil, viewport_width: Int? = nil, viewport_height: Int? = nil, screen_width: Int? = nil, screen_height: Int? = nil, unique: Bool? = nil) {
25+
init(type: EventType, hostname: String, event: String, ua: String? = nil, path: String? = nil, language: String? = nil, timezone: String? = nil, viewport_width: Int? = nil, viewport_height: Int? = nil, screen_width: Int? = nil, screen_height: Int? = nil, unique: Bool? = nil, metadata: String? = nil) {
2526
self.type = type
2627
self.hostname = hostname
2728
self.event = event
@@ -34,6 +35,7 @@ internal struct Event: Encodable {
3435
self.screen_width = screen_width
3536
self.screen_height = screen_height
3637
self.unique = unique
38+
self.metadata = metadata
3739
}
3840
}
3941

Sources/SimpleAnalytics/SimpleAnalytics.swift

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,20 @@ final public class SimpleAnalytics: NSObject {
6666

6767
/// Track a pageview
6868
/// - Parameter path: The path of the page as string array, for example: `["list", "detailview", "edit"]`
69-
public func track(path: [String]) {
70-
self.trackPageView(path: pathToString(path: path))
69+
/// - Parameter metadata: An optional dictionary of metadata to be sent with the pageview. `["plan": "premium", "referrer": "landing_page"]`
70+
public func track(path: [String], metadata: [String: Any]? = nil) {
71+
self.trackPageView(path: pathToString(path: path), metadata: metadataToJsonString(metadata: metadata))
7172
}
7273

7374
/// Track an event
7475
/// - Parameter event: The event name
7576
/// - Parameter path: optional path array where the event took place, for example: `["list", "detailview", "edit"]`
76-
public func track(event: String, path: [String] = []) {
77-
self.trackEvent(event: event, path: pathToString(path: path))
77+
/// - Parameter metadata: An optional dictionary of metadata to be sent with the pageview. `["plan": "premium", "referrer": "landing_page"]`
78+
public func track(event: String, path: [String] = [], metadata: [String: Any]? = nil) {
79+
self.trackEvent(event: event, path: pathToString(path: path), metadata: metadataToJsonString(metadata: metadata))
7880
}
7981

80-
internal func trackPageView(path: String) {
82+
internal func trackPageView(path: String, metadata: String? = nil) {
8183
guard !isOptedOut else {
8284
return
8385
}
@@ -89,13 +91,14 @@ final public class SimpleAnalytics: NSObject {
8991
path: path,
9092
language: userLanguage,
9193
timezone: userTimezone,
92-
unique: isUnique()
94+
unique: isUnique(),
95+
metadata: metadata
9396
)
9497

9598
RequestDispatcher.sendEventRequest(event: event)
9699
}
97100

98-
internal func trackEvent(event: String, path: String = "") {
101+
internal func trackEvent(event: String, path: String = "", metadata: String? = nil) {
99102
guard !isOptedOut else {
100103
return
101104
}
@@ -107,7 +110,8 @@ final public class SimpleAnalytics: NSObject {
107110
path: path,
108111
language: userLanguage,
109112
timezone: userTimezone,
110-
unique: isUnique()
113+
unique: isUnique(),
114+
metadata: metadata
111115
)
112116
RequestDispatcher.sendEventRequest(event: event)
113117
}
@@ -125,6 +129,21 @@ final public class SimpleAnalytics: NSObject {
125129
return "/\(safePath.joined(separator: "/"))"
126130
}
127131

132+
/// Serializes metadata dictionary into a JSON string.
133+
/// - Parameter metadata: The metadata dictionary, which is optional.
134+
/// - Returns: A JSON string representation of the metadata or nil if serialization fails or metadata is nil/empty.
135+
internal func metadataToJsonString(metadata: [String: Any]?) -> String? {
136+
guard let metadata = metadata, !metadata.isEmpty else { return nil }
137+
138+
do {
139+
let data = try JSONSerialization.data(withJSONObject: metadata, options: [])
140+
return String(data: data, encoding: .utf8)
141+
} catch {
142+
print("Error serializing metadata to JSON string: \(error)")
143+
return nil
144+
}
145+
}
146+
128147
/// Simple Analytics uses the `isUnique` flag to determine visitors from pageviews. The first event/pageview for the day
129148
/// should get this `isUnique` flag.
130149
/// - Returns: if this is a unique first visit for today

Tests/SimpleAnalyticsTests/Swift_SimpleAnalyticsTests.swift

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,24 @@ final class Swift_SimpleAnalyticsTests: XCTestCase {
1111

1212
}
1313

14+
func testPageviewWithMetadata() throws {
15+
let expectation = XCTestExpectation(description: "Log a pageview")
16+
17+
let tracker = SimpleAnalytics(hostname: "simpleanalyticsswift.app")
18+
19+
let metadataDictionary = ["plan": "premium", "meta": "data"]
20+
do {
21+
let metadataData = try JSONSerialization.data(withJSONObject: metadataDictionary, options: [])
22+
let metadataJsonString = String(data: metadataData, encoding: .utf8)!
23+
tracker.trackPageView(path: "/test", metadata: metadataJsonString)
24+
} catch {
25+
XCTFail("Failed to serialize metadata: \(error)")
26+
}
27+
28+
wait(for: [expectation], timeout: 10.0)
29+
30+
}
31+
1432
func testEvent() throws {
1533
let expectation = XCTestExpectation(description: "Log a pageview")
1634

@@ -20,6 +38,23 @@ final class Swift_SimpleAnalyticsTests: XCTestCase {
2038

2139
}
2240

41+
func testEventWithMetadata() throws {
42+
let expectation = XCTestExpectation(description: "Log a pageview")
43+
44+
let tracker = SimpleAnalytics(hostname: "simpleanalyticsswift.app")
45+
46+
let metadataDictionary = ["plan": "premium", "meta": "data"]
47+
do {
48+
let metadataData = try JSONSerialization.data(withJSONObject: metadataDictionary, options: [])
49+
let metadataJsonString = String(data: metadataData, encoding: .utf8)!
50+
tracker.trackEvent(event: "test", metadata: metadataJsonString)
51+
} catch {
52+
XCTFail("Failed to serialize metadata: \(error)")
53+
}
54+
wait(for: [expectation], timeout: 10.0)
55+
56+
}
57+
2358
func testEventWithPath() throws {
2459
let expectation = XCTestExpectation(description: "Log an event")
2560

@@ -28,6 +63,25 @@ final class Swift_SimpleAnalyticsTests: XCTestCase {
2863
wait(for: [expectation], timeout: 10.0)
2964

3065

66+
}
67+
68+
69+
func testEventWithPathAndMetadata() throws {
70+
let expectation = XCTestExpectation(description: "Log an event")
71+
72+
let tracker = SimpleAnalytics(hostname: "simpleanalyticsswift.app")
73+
74+
let metadataDictionary = ["plan": "premium", "meta": "data"]
75+
do {
76+
let metadataData = try JSONSerialization.data(withJSONObject: metadataDictionary, options: [])
77+
let metadataJsonString = String(data: metadataData, encoding: .utf8)!
78+
tracker.trackEvent(event: "test", path: "/testpath1/testpath2")
79+
} catch {
80+
XCTFail("Failed to serialize metadata: \(error)")
81+
}
82+
wait(for: [expectation], timeout: 10.0)
83+
84+
3185
}
3286

3387
func testInvalidHostname() throws {

0 commit comments

Comments
 (0)