From 9c50962304610749480d53eacb0f7b42ec00066b Mon Sep 17 00:00:00 2001 From: Brandon Sneed Date: Tue, 9 Jul 2024 09:53:33 -0700 Subject: [PATCH 1/2] Make additional events options. --- .../SegmentAmplitude/AmplitudeSession.swift | 100 ++++++++++++------ Sources/SegmentAmplitude/Constants.swift | 22 ++++ Sources/SegmentAmplitude/Session.swift | 14 --- 3 files changed, 89 insertions(+), 47 deletions(-) create mode 100644 Sources/SegmentAmplitude/Constants.swift diff --git a/Sources/SegmentAmplitude/AmplitudeSession.swift b/Sources/SegmentAmplitude/AmplitudeSession.swift index a0ca4c6..2b80feb 100644 --- a/Sources/SegmentAmplitude/AmplitudeSession.swift +++ b/Sources/SegmentAmplitude/AmplitudeSession.swift @@ -40,22 +40,13 @@ public class AmplitudeSession: EventPlugin, iOSLifecycle { public var type = PluginType.enrichment public weak var analytics: Analytics? - internal struct Constants { - static let ampPrefix = "[Amplitude] " - - static let ampSessionEndEvent = "session_end" - static let ampSessionStartEvent = "session_start" - static let ampAppInstalledEvent = "\(ampPrefix)Application Installed" - static let ampAppUpdatedEvent = "\(ampPrefix)Application Updated" - static let ampAppOpenedEvent = "\(ampPrefix)Application Opened" - static let ampAppBackgroundedEvent = "\(ampPrefix)Application Backgrounded" - static let ampDeepLinkOpenedEvent = "\(ampPrefix)Deep Link Opened" - static let ampScreenViewedEvent = "\(ampPrefix)Screen Viewed" - static let ampScreenNameProperty = "\(ampPrefix)Screen Name" - } - public var logging: Bool = false + private let enableSessionEvents: Bool + private let enableLifecycleEvents: Bool + private let enableScreenEvents: Bool + private let enableDeepLinkEvents: Bool + @Atomic private var active = false @Atomic private var inForeground: Bool = false @Atomic private var resetPending: Bool = false @@ -75,9 +66,20 @@ public class AmplitudeSession: EventPlugin, iOSLifecycle { } } - public init() { + public init( + enableSessionEvents: Bool = true, + enableLifecycleEvents: Bool = false, + enableScreenEvents: Bool = false, + enableDeepLinkEvents: Bool = false + ) { self.sessionID = storage.read(key: Storage.Constants.previousSessionID) ?? -1 self.lastEventTime = storage.read(key: Storage.Constants.lastEventTime) ?? -1 + + self.enableSessionEvents = enableSessionEvents + self.enableScreenEvents = enableScreenEvents + self.enableLifecycleEvents = enableLifecycleEvents + self.enableDeepLinkEvents = enableDeepLinkEvents + debugLog("startup sessionID = \(sessionID)") } @@ -112,6 +114,8 @@ public class AmplitudeSession: EventPlugin, iOSLifecycle { startNewSessionIfNecessary() // handle screen + + // this code works off the destination action logic. if var screenEvent = workingEvent as? ScreenEvent, let screenName = screenEvent.name { var adjustedProps = screenEvent.properties // amp needs the `name` in the properties @@ -121,8 +125,22 @@ public class AmplitudeSession: EventPlugin, iOSLifecycle { adjustedProps?.setValue(screenName, forKeyPath: KeyPath("name")) } screenEvent.properties = adjustedProps + + // if we're sending Amplitude's definition of a screen event ... + if enableScreenEvents { + // set the keyname amplitude wants + adjustedProps?.setValue(screenName, forKeyPath: KeyPath(Constants.ampScreenNameProperty)) + // remove the unnecessary `name` property. + adjustedProps = try? adjustedProps?.remove(key: "name") + // send a new track call for amplitude to pick up the screen. + analytics?.track(name: Constants.ampScreenViewedEvent, properties: adjustedProps) + // keep our current screen event from going to amplitude. + screenEvent.integrations?.setValue(false, forKeyPath: KeyPath(key)) + } + workingEvent = screenEvent as? T } + // handle track if var trackEvent = workingEvent as? TrackEvent { @@ -133,10 +151,18 @@ public class AmplitudeSession: EventPlugin, iOSLifecycle { resetPending = false eventSessionID = sessionID debugLog("NewSession = \(eventSessionID)") + if !enableSessionEvents { + // don't send these events, so return nil to drop it. + return nil + } } if eventName == Constants.ampSessionEndEvent { debugLog("EndSession = \(eventSessionID)") + if !enableSessionEvents { + // don't send these events, so return nil to drop it. + return nil + } } // if it's amp specific stuff, disable all the integrations except for amp. @@ -146,26 +172,34 @@ public class AmplitudeSession: EventPlugin, iOSLifecycle { trackEvent.integrations = integrations } + if enableDeepLinkEvents { + if eventName == "Deep Link Opened" { + analytics?.track(name: Constants.ampDeepLinkOpenedEvent, properties: trackEvent.properties) + } + } + // handle events that need to be re-generated back to amplitude. // block the originals from going to amplitude as well. - switch trackEvent.event { - case "Application Opened": - analytics?.track(name: Constants.ampAppOpenedEvent, properties: trackEvent.properties) - trackEvent.integrations?.setValue(false, forKeyPath: KeyPath(key)) - case "Application Installed": - analytics?.track(name: Constants.ampAppInstalledEvent, properties: trackEvent.properties) - trackEvent.integrations?.setValue(false, forKeyPath: KeyPath(key)) - case "Application Updated": - analytics?.track(name: Constants.ampAppUpdatedEvent, properties: trackEvent.properties) - trackEvent.integrations?.setValue(false, forKeyPath: KeyPath(key)) - case "Application Backgrounded": - analytics?.track(name: Constants.ampAppBackgroundedEvent, properties: trackEvent.properties) - trackEvent.integrations?.setValue(false, forKeyPath: KeyPath(key)) - case "Application Foregrounded": - // amplitude doesn't need this one, it's redundant. - trackEvent.integrations?.setValue(false, forKeyPath: KeyPath(key)) - default: - break + if enableLifecycleEvents { + switch trackEvent.event { + case "Application Opened": + analytics?.track(name: Constants.ampAppOpenedEvent, properties: trackEvent.properties) + trackEvent.integrations?.setValue(false, forKeyPath: KeyPath(key)) + case "Application Installed": + analytics?.track(name: Constants.ampAppInstalledEvent, properties: trackEvent.properties) + trackEvent.integrations?.setValue(false, forKeyPath: KeyPath(key)) + case "Application Updated": + analytics?.track(name: Constants.ampAppUpdatedEvent, properties: trackEvent.properties) + trackEvent.integrations?.setValue(false, forKeyPath: KeyPath(key)) + case "Application Backgrounded": + analytics?.track(name: Constants.ampAppBackgroundedEvent, properties: trackEvent.properties) + trackEvent.integrations?.setValue(false, forKeyPath: KeyPath(key)) + case "Application Foregrounded": + // amplitude doesn't need this one, it's redundant. + trackEvent.integrations?.setValue(false, forKeyPath: KeyPath(key)) + default: + break + } } workingEvent = trackEvent as? T diff --git a/Sources/SegmentAmplitude/Constants.swift b/Sources/SegmentAmplitude/Constants.swift new file mode 100644 index 0000000..0230d17 --- /dev/null +++ b/Sources/SegmentAmplitude/Constants.swift @@ -0,0 +1,22 @@ +// +// Constants.swift +// +// +// Created by Brandon Sneed on 7/9/24. +// + +import Foundation + +internal struct Constants { + static let ampPrefix = "[Amplitude] " + + static let ampSessionEndEvent = "session_end" + static let ampSessionStartEvent = "session_start" + static let ampAppInstalledEvent = "\(ampPrefix)Application Installed" + static let ampAppUpdatedEvent = "\(ampPrefix)Application Updated" + static let ampAppOpenedEvent = "\(ampPrefix)Application Opened" + static let ampAppBackgroundedEvent = "\(ampPrefix)Application Backgrounded" + static let ampDeepLinkOpenedEvent = "\(ampPrefix)Deep Link Opened" + static let ampScreenViewedEvent = "\(ampPrefix)Screen Viewed" + static let ampScreenNameProperty = "\(ampPrefix)Screen Name" +} diff --git a/Sources/SegmentAmplitude/Session.swift b/Sources/SegmentAmplitude/Session.swift index 5650834..88dbf05 100644 --- a/Sources/SegmentAmplitude/Session.swift +++ b/Sources/SegmentAmplitude/Session.swift @@ -11,20 +11,6 @@ import Segment // MARK: - Amplitude Session Management internal class Session { - internal struct Constants { - static let ampPrefix = "[Amplitude] " - - static let ampSessionEndEvent = "session_end" - static let ampSessionStartEvent = "session_start" - static let ampAppInstalledEvent = "\(ampPrefix)Application Installed" - static let ampAppUpdatedEvent = "\(ampPrefix)Application Updated" - static let ampAppOpenedEvent = "\(ampPrefix)Application Opened" - static let ampAppBackgroundedEvent = "\(ampPrefix)Application Backgrounded" - static let ampDeepLinkOpenedEvent = "\(ampPrefix)Deep Link Opened" - static let ampScreenViewedEvent = "\(ampPrefix)Screen Viewed" - static let ampRevenueEvent = "revenue_amount" - } - @Atomic var sessionID: Int64 { didSet { storage.write(key: Storage.Constants.previousSessionID, value: sessionID) From bbab2492065378984a28c35f88a879e367ac7d43 Mon Sep 17 00:00:00 2001 From: Brandon Sneed Date: Tue, 9 Jul 2024 09:54:11 -0700 Subject: [PATCH 2/2] Set up example for testing --- Example/BasicExample/BasicExample/BasicExampleApp.swift | 7 ++++++- Example/BasicExample/BasicExample/ContentView.swift | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Example/BasicExample/BasicExample/BasicExampleApp.swift b/Example/BasicExample/BasicExample/BasicExampleApp.swift index 5616211..6212939 100644 --- a/Example/BasicExample/BasicExample/BasicExampleApp.swift +++ b/Example/BasicExample/BasicExample/BasicExampleApp.swift @@ -26,7 +26,12 @@ extension Analytics { instance = Analytics(configuration: Configuration(writeKey: "") .flushAt(3) .trackApplicationLifecycleEvents(true)) - instance?.add(plugin: AmplitudeSession()) + instance?.add(plugin: AmplitudeSession( + enableSessionEvents: true, + enableLifecycleEvents: true, + enableScreenEvents: true, + enableDeepLinkEvents: true + )) } return instance! diff --git a/Example/BasicExample/BasicExample/ContentView.swift b/Example/BasicExample/BasicExample/ContentView.swift index d06038c..591b7f8 100644 --- a/Example/BasicExample/BasicExample/ContentView.swift +++ b/Example/BasicExample/BasicExample/ContentView.swift @@ -18,7 +18,7 @@ struct ContentView: View { Text("Track") }).padding(6) Button(action: { - Analytics.main.screen(title: "Screen appeared") + Analytics.main.screen(title: "MyScreen") }, label: { Text("Screen") }).padding(6)