Analytics-Kotlin Plugin Architecture
Segment's plugin architecture lets you modify and augment how the analytics client works. From modifying event payloads to changing analytics functionality, plugins help to speed up the process of getting things done.
Plugins are run through a timeline, which executes in order of insertion based on their types. Segment has these five types:
| Type | Details |
|---|---|
| before | Executes before event processing begins. |
| enrichment | Executes as the first level of event processing. |
| destination | Executes as events begin to pass off to destinations. |
| after | Executes after all event processing completes. You can use this to perform cleanup operations. |
| utility | Executes only with manual calls such as Logging. |
There are three basic types of plugins that you can use as a foundation for modifying functionality. They are: Plugin, EventPlugin, and DestinationPlugin.
Plugin acts on any event payload going through the timeline.
For example, if you want to add something to the context object of any event payload as an enrichment:
1class SomePlugin: Plugin {2override val type = Plugin.Type.Enrichment34override lateinit var analytics: Analytics56override fun execute(event: BaseEvent): BaseEvent? {7event.putInContext("foo", "bar")8return event9}10}
EventPlugin is a plugin interface that acts on specific event types. You can choose the event types by only overriding the event functions you want.
For example, if you only want to act on Track and Identify events:
1class SomePlugin: EventPlugin {2override fun track(event: TrackEvent): BaseEvent? {3// code to modify track event4return event5}6override fun identify(event: TrackEvent): BaseEvent? {7// code to modify identify event8return event9}10}
The DestinationPlugin interface is commonly used for device-mode destinations. This plugin contains an internal timeline that follows the same process as the analytics timeline, enabling you to modify and augment how events reach a particular destination.
For example, if you want to implement a device-mode destination plugin for Amplitude, you can use this:
1class AmplitudePlugin: DestinationPlugin() {2override val key = "Amplitude" // This is the name of the destination plugin, it is used to retrieve settings internally34val amplitudeSDK: Amplitude // This is an instance of the partner SDK56init { // Initializing the partner SDK and setting things up7amplitudeSDK = Amplitude.instance8amplitudeSDK.initialize(applicationContext, "API_KEY");9}1011/*12* Implementing this function allows this plugin to hook into any track events13* coming into the analytics timeline14*/15override fun track(event: TrackEvent): BaseEvent? {16amplitudeSDK.logEvent(event.name)17return event18}19}
setup(Analytics): Use this function to setup your plugin. This implicitly calls once the plugin registers.update(Settings): Use this function to react to any settings updates. This implicitly calls when settings update. You can force a settings update by callinganalytics.checkSettings().AndroidLifecyclehooks Plugins can also hook intoAndroidLifecyclefunctions by implementing an interface. These functions call implicitly as the lifecycle events process.DestinationPlugintimeline: The destination plugin contains an internal timeline that follows the same process as the analytics timeline, enabling you to modify/augment how events reach the particular destination. For example if you only wanted to add a context key when sending an event toAmplitude:
1val amplitudePlugin = AmplitudePlugin()2analytics.add(amplitudePlugin) // add amplitudePlugin to the analytics client34val amplitudeEnrichment = object: Plugin {5override val type = Plugin.Type.Enrichment67override lateinit var analytics: Analytics89override fun execute(event: BaseEvent): BaseEvent? {10event.putInContext("foo", "bar")11return event12}13}1415amplitudePlugin.add(amplitudeEnrichment) // add enrichment plugin to amplitude timeline
Adding plugins enable you to modify your analytics implementation to best fit your needs. You can add a plugin using this:
1val yourPlugin = SomePlugin()2analytics.add(yourPlugin)
Though you can add plugins anywhere in your code, it's best to implement your plugin when you configure the client.
Here's an example of adding a plugin to the context object of any event payload as an enrichment:
1class SomePlugin: Plugin {2override val type = Plugin.Type.Enrichment34override lateinit var analytics: Analytics56override fun execute(event: BaseEvent): BaseEvent? {7event.putInContext("foo", "bar")8return event9}10}11val yourPlugin = SomePlugin()12analytics.add(yourPlugin)
If Segment doesn't support your Kotlin destination, you can build your own with the template Segment provides.
To build your own Kotlin destination using a plugin template:
- Go to the Kotlin Destination Plugin Template.
- Click Use this template.
- Enter a name for the repository.
- Click Create repository from template.
- Go to lib > src > main > java/dmn/your/pkg/destination in your repository.
- Click the MyDestination.kt.
- Complete the
TODOsections in the sample code with the appropriate information for your destination. Segment recommends you to change the package name before you finalize your build. - Commit your changes.
You can unit test your destination to make sure it works. Segment recommends you to use the testing template as a starter and to build upon it to get test coverage of most scenarios.
To test your destination:
- Go to lib > src > test > java/dmn/your/pkg/destination.
- Click MyDestinationTests.kt.
- Complete the
TODOsections in the sample code with the appropriate information for your destination. - Commit your changes.
Segment recommends that you test your destination implementation end-to-end. Send some sample analytics events and ensure that they reach the destination.