Skip to content

Commit f0f3332

Browse files
Merge pull request #8 from chazchazchaz/feature/app-group-key-storage
feature/app-group-storage
2 parents ec7bd4c + 8ba7561 commit f0f3332

File tree

3 files changed

+47
-2
lines changed

3 files changed

+47
-2
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ You can provide an optional path to track alongside the event.
6060
SimpleAnalytics.shared.track(event: "logged in", path: ["login", "social"])
6161
```
6262

63+
### Tracking Visitors for Apps + Widgets
64+
If you have an app + widget(s), by default one visit per day per target (app, widget) is treated as separate 'visitors'. This means that if you have an app with a small and medium widget, one person using the core app and both widgets will show in your SimpleAnalytics dashboard as 3 visitors. However, you can ensure one visitor only appears once per day by creating an App Group in your Xcode project. Create a new App Group ([instructions](https://developer.apple.com/documentation/xcode/configuring-app-groups)) in each of your targets (Project > Targets > Signing & Capabilities > App Groups) with the same name. Use this app group name in your SimpleAnalytics instance.
65+
```swift
66+
let simpleAnalytics = SimpleAnalytics(hostname: "app.simpleanalytics.com", sharedDefaultsSuiteName: "group.com.simpleanlytics.app")
67+
```
68+
6369
## Examples
6470
### SwiftUI example
6571
In SwiftUI, a good place to put the Pageview tracking code is in your view `.onAppear{}` modifier.

Sources/SimpleAnalytics/SimpleAnalytics.swift

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ final public class SimpleAnalytics: NSObject {
3030
private let userTimezone: String
3131
/// The last date a unique visit was tracked.
3232
private var visitDate: Date?
33+
private var sharedDefaultsSuiteName: String?
3334

3435
/// Defines if the user is opted out. When set to `true`, all tracking will be skipped. This is persisted between sessions.
3536
public var isOptedOut: Bool {
@@ -51,6 +52,18 @@ final public class SimpleAnalytics: NSObject {
5152
self.visitDate = UserDefaults.standard.object(forKey: Keys.visitDateKey) as? Date
5253
}
5354

55+
/// Create the SimpleAnalytics instance that can be used to trigger events and pageviews.
56+
/// - Parameter hostname: The hostname as found in SimpleAnalytics, without `https://`
57+
/// - Parameter: sharedDefaultsSuiteName: When extensions (such as a main app and widget) have a set of sharedDefaults (using an App Group) that unique user can be counted once using this (instead of two or more times when using app and widget, etc.)
58+
public init(hostname: String, sharedDefaultsSuiteName: String) {
59+
self.hostname = hostname
60+
self.userAgent = UserAgent.userAgentString()
61+
self.userLanguage = Locale.current.identifier
62+
self.userTimezone = TimeZone.current.identifier
63+
self.sharedDefaultsSuiteName = sharedDefaultsSuiteName
64+
self.visitDate = UserDefaults(suiteName: sharedDefaultsSuiteName)?.object(forKey: Keys.visitDateKey) as? Date
65+
}
66+
5467
/// Track a pageview
5568
/// - Parameter path: The path of the page as string array, for example: `["list", "detailview", "edit"]`
5669
public func track(path: [String]) {
@@ -123,13 +136,21 @@ final public class SimpleAnalytics: NSObject {
123136
} else {
124137
// Last visit is not in today, so unique.
125138
self.visitDate = Date()
126-
UserDefaults.standard.set(self.visitDate, forKey: Keys.visitDateKey)
139+
if let sharedDefaults = UserDefaults(suiteName: self.sharedDefaultsSuiteName) {
140+
sharedDefaults.set(self.visitDate, forKey: Keys.visitDateKey)
141+
} else {
142+
UserDefaults.standard.set(self.visitDate, forKey: Keys.visitDateKey)
143+
}
127144
return true
128145
}
129146
} else {
130147
// No visit date yet, initialize it
131148
visitDate = Date()
132-
UserDefaults.standard.set(visitDate, forKey: Keys.visitDateKey)
149+
if let sharedDefaults = UserDefaults(suiteName: self.sharedDefaultsSuiteName) {
150+
sharedDefaults.set(visitDate, forKey: Keys.visitDateKey)
151+
} else {
152+
UserDefaults.standard.set(visitDate, forKey: Keys.visitDateKey)
153+
}
133154
return true
134155
}
135156
}

Tests/SimpleAnalyticsTests/Swift_SimpleAnalyticsTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,24 @@ final class Swift_SimpleAnalyticsTests: XCTestCase {
4848

4949
}
5050

51+
func testPageviewWithDefaultsGroup() throws {
52+
let expectation = XCTestExpectation(description: "Log a pageview")
53+
54+
let tracker = SimpleAnalytics(hostname: "simpleanalyticsswift.app", sharedDefaultsSuiteName: "app.yourapp.com")
55+
tracker.trackPageView(path: "/test")
56+
wait(for: [expectation], timeout: 10.0)
57+
58+
}
59+
60+
func testEventWithDefaultsGroup() throws {
61+
let expectation = XCTestExpectation(description: "Log a pageview")
62+
63+
let tracker = SimpleAnalytics(hostname: "simpleanalyticsswift.app", sharedDefaultsSuiteName: "app.yourapp.com")
64+
tracker.trackEvent(event: "test")
65+
wait(for: [expectation], timeout: 10.0)
66+
67+
}
68+
5169
func testPath() {
5270

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

0 commit comments

Comments
 (0)