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

Add reset method to MatomoTracker #418

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions MatomoTracker/MatomoTracker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -468,3 +468,24 @@ extension MatomoTracker {
/// The version of the Matomo SDKs
@objc public static let sdkVersion = "7.3"
}

extension MatomoTracker {
/// Resets all session, visitor and campaign information.
///
/// Dispatches events before restting itself.
/// After calling this method this instance behaves like the app has been freshly installed.
public func reset() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, first think in this function, we should ensure we are running on the main thread.

dispatch()

matomoUserDefaults.reset()

visitor = Visitor.current(in: matomoUserDefaults)
session = Session.current(in: matomoUserDefaults)
dimensions = []
customVariables = []
campaignName = nil
campaignKeyword = nil

startNewSession()
}
}
Comment on lines +472 to +491
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this function we do have the risk, that if we add any properties, we forget to reset them in here as well. Unfortunately I don't have a great idea how to prevent this. I still wanted to bring this up here in case you have an idea.

One option would certainly be to replace the instance of MatomoTracker. But since the SDK doesn't provide any instance, this would be left for the user and all we could offer in this function here would be to reset the persisted data. I don't think that's great.

12 changes: 12 additions & 0 deletions MatomoTracker/MatomoUserDefaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,18 @@ internal struct MatomoUserDefaults {
userDefaults.set(newValue, forKey: MatomoUserDefaults.Key.lastOrder)
}
}

func reset() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about the term reset here. I was wondering, since this is a wrapper of UserDefaults if we want to keep the name close to the names of UserDefaults. So something like removeAllObjects or so. What do you think?

userDefaults.removeObject(forKey: Key.totalNumberOfVisits)
userDefaults.removeObject(forKey: Key.currentVisitTimestamp)
userDefaults.removeObject(forKey: Key.previousVistsTimestamp)
userDefaults.removeObject(forKey: Key.firstVistsTimestamp)
userDefaults.removeObject(forKey: Key.clientID)
userDefaults.removeObject(forKey: Key.forcedVisitorID)
userDefaults.removeObject(forKey: Key.visitorUserID)
userDefaults.removeObject(forKey: Key.optOut)
userDefaults.removeObject(forKey: Key.lastOrder)
Comment on lines +104 to +112
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could see the risk, once we add a new property that is stored in the user defaults, that we forget to remove it here as well. What do you think about changing the internal struct Key to an enum Key: String, CaseIterable so we can iterate over all of them here.

}
}

extension MatomoUserDefaults {
Expand Down
75 changes: 75 additions & 0 deletions MatomoTrackerTests/TrackerSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,80 @@ class TrackerSpec: QuickSpec {
expect(tracker2.forcedVisitorId) == "0123456789abcdef"
}
}
describe("reset") {
it("generates new visitor") {
var queuedEvents = [Event]()
let queue = QueueMock()
let tracker = MatomoTracker.fixture(queue: queue, dispatcher: DispatcherMock())
queue.enqueueEventsHandler = { events, _ in
queuedEvents += events
}

tracker.track(view: ["spec_view"])
tracker.reset()
tracker.track(view: ["spec_view"])

expect(queuedEvents.count) == 2
expect(queuedEvents.first?.visitor.id).toNot(equal(queuedEvents.last?.visitor.id))
}
it("clears session information") {
var queuedEvent: Event? = nil
let queue = QueueMock()
let tracker = MatomoTracker.fixture(queue: queue, dispatcher: DispatcherMock())
queue.enqueueEventsHandler = { events, _ in
queuedEvent = events.first
}

tracker.startNewSession()
tracker.reset()
tracker.track(view: ["spec_view"])

expect(queuedEvent?.session.sessionsCount) == 1
}
it("clears dimensions") {
var queuedEvent: Event? = nil
let queue = QueueMock()
let tracker = MatomoTracker.fixture(queue: queue, dispatcher: DispatcherMock())
queue.enqueueEventsHandler = { events, _ in
queuedEvent = events.first
}

tracker.set(dimension: CustomDimension(index: 0, value: "fake-dimension"))
tracker.reset()
tracker.track(view: ["spec_view"])

expect(queuedEvent?.dimensions).to(beEmpty())
}
it("removes all custom variables") {
var queuedEvent: Event? = nil
let queue = QueueMock()
let tracker = MatomoTracker.fixture(queue: queue, dispatcher: DispatcherMock())
queue.enqueueEventsHandler = { events, _ in
queuedEvent = events.first
}

tracker.set(customVariable: CustomVariable(index: 0, name: "fake-variable", value: "fake-value"))
tracker.reset()
tracker.track(view: ["spec_view"])

expect(queuedEvent?.customVariables).to(beEmpty())
}
it("clear campaigns") {
var queuedEvent: Event? = nil
let queue = QueueMock()
let tracker = MatomoTracker.fixture(queue: queue, dispatcher: DispatcherMock())
queue.enqueueEventsHandler = { events, _ in
queuedEvent = events.first
}

tracker.trackCampaign(name: "fake-campaign", keyword: "fake-keyword")
tracker.reset()
tracker.track(view: ["spec_view"])

expect(queuedEvent).toNot(beNil())
expect(queuedEvent?.campaignName).to(beNil())
expect(queuedEvent?.campaignKeyword).to(beNil())
}
}
}
}