Skip to content

Commit

Permalink
Merge pull request #5 from chazchazchaz/feature/metadata
Browse files Browse the repository at this point in the history
Feature/metadata
  • Loading branch information
roelvanderkraan authored Aug 6, 2024
2 parents f0f3332 + cb2a070 commit a578954
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 9 deletions.
4 changes: 3 additions & 1 deletion Sources/SimpleAnalytics/Event.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ internal struct Event: Encodable {
let screen_width: Int?
let screen_height: Int?
let unique: Bool?
var metadata: String?

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) {
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) {
self.type = type
self.hostname = hostname
self.event = event
Expand All @@ -34,6 +35,7 @@ internal struct Event: Encodable {
self.screen_width = screen_width
self.screen_height = screen_height
self.unique = unique
self.metadata = metadata
}
}

Expand Down
35 changes: 27 additions & 8 deletions Sources/SimpleAnalytics/SimpleAnalytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,20 @@ final public class SimpleAnalytics: NSObject {

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

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

internal func trackPageView(path: String) {
internal func trackPageView(path: String, metadata: String? = nil) {
guard !isOptedOut else {
return
}
Expand All @@ -89,13 +91,14 @@ final public class SimpleAnalytics: NSObject {
path: path,
language: userLanguage,
timezone: userTimezone,
unique: isUnique()
unique: isUnique(),
metadata: metadata
)

RequestDispatcher.sendEventRequest(event: event)
}

internal func trackEvent(event: String, path: String = "") {
internal func trackEvent(event: String, path: String = "", metadata: String? = nil) {
guard !isOptedOut else {
return
}
Expand All @@ -107,7 +110,8 @@ final public class SimpleAnalytics: NSObject {
path: path,
language: userLanguage,
timezone: userTimezone,
unique: isUnique()
unique: isUnique(),
metadata: metadata
)
RequestDispatcher.sendEventRequest(event: event)
}
Expand All @@ -125,6 +129,21 @@ final public class SimpleAnalytics: NSObject {
return "/\(safePath.joined(separator: "/"))"
}

/// Serializes metadata dictionary into a JSON string.
/// - Parameter metadata: The metadata dictionary, which is optional.
/// - Returns: A JSON string representation of the metadata or nil if serialization fails or metadata is nil/empty.
internal func metadataToJsonString(metadata: [String: Any]?) -> String? {
guard let metadata = metadata, !metadata.isEmpty else { return nil }

do {
let data = try JSONSerialization.data(withJSONObject: metadata, options: [])
return String(data: data, encoding: .utf8)
} catch {
print("Error serializing metadata to JSON string: \(error)")
return nil
}
}

/// Simple Analytics uses the `isUnique` flag to determine visitors from pageviews. The first event/pageview for the day
/// should get this `isUnique` flag.
/// - Returns: if this is a unique first visit for today
Expand Down
54 changes: 54 additions & 0 deletions Tests/SimpleAnalyticsTests/Swift_SimpleAnalyticsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@ final class Swift_SimpleAnalyticsTests: XCTestCase {

}

func testPageviewWithMetadata() throws {
let expectation = XCTestExpectation(description: "Log a pageview")

let tracker = SimpleAnalytics(hostname: "simpleanalyticsswift.app")

let metadataDictionary = ["plan": "premium", "meta": "data"]
do {
let metadataData = try JSONSerialization.data(withJSONObject: metadataDictionary, options: [])
let metadataJsonString = String(data: metadataData, encoding: .utf8)!
tracker.trackPageView(path: "/test", metadata: metadataJsonString)
} catch {
XCTFail("Failed to serialize metadata: \(error)")
}

wait(for: [expectation], timeout: 10.0)

}

func testEvent() throws {
let expectation = XCTestExpectation(description: "Log a pageview")

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

}

func testEventWithMetadata() throws {
let expectation = XCTestExpectation(description: "Log a pageview")

let tracker = SimpleAnalytics(hostname: "simpleanalyticsswift.app")

let metadataDictionary = ["plan": "premium", "meta": "data"]
do {
let metadataData = try JSONSerialization.data(withJSONObject: metadataDictionary, options: [])
let metadataJsonString = String(data: metadataData, encoding: .utf8)!
tracker.trackEvent(event: "test", metadata: metadataJsonString)
} catch {
XCTFail("Failed to serialize metadata: \(error)")
}
wait(for: [expectation], timeout: 10.0)

}

func testEventWithPath() throws {
let expectation = XCTestExpectation(description: "Log an event")

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


}


func testEventWithPathAndMetadata() throws {
let expectation = XCTestExpectation(description: "Log an event")

let tracker = SimpleAnalytics(hostname: "simpleanalyticsswift.app")

let metadataDictionary = ["plan": "premium", "meta": "data"]
do {
let metadataData = try JSONSerialization.data(withJSONObject: metadataDictionary, options: [])
let metadataJsonString = String(data: metadataData, encoding: .utf8)!
tracker.trackEvent(event: "test", path: "/testpath1/testpath2")
} catch {
XCTFail("Failed to serialize metadata: \(error)")
}
wait(for: [expectation], timeout: 10.0)


}

func testInvalidHostname() throws {
Expand Down

0 comments on commit a578954

Please sign in to comment.