Add Segment driven consent management support for your application via this plugin for Analytics-Swift
This plugin provides the framework to integration Consent Management Platform (CMP) SDKs like OneTrust to supply consent status and potential block events going to device mode destinations.
Read more about Segment's Consent Management solutions here, as well as enabling it for your workspace.
Consent Management is the management of a user’s consent preferences related to privacy. You might be familiar with the Privacy Pop-ups that have become mandated recently that ask the user if he or she consents to the use of certain category of cookies:
The Privacy pop-up asks the user if he or she will consent to the use of cookies and allows the user to customize their consent by turning on/off different categories of cookies.
After the user selects “Allow All” or “Save Preferences” a callback is fired and the owner of the website is notified as to the consent preferences of a given user. The website owner must then store that consent preference and abide by it. Any rejected cookies must not be set or read to avoid large fines that can be handed down by government authorities.
Additionally, besides the initial pop-up the app owner must give users a way to later change any preferences they originally selected. This is usually accomplished by providing a button to display the customization screen.
Segment provides a framework for users to integrate any CMP they choose and use the Segment web app to map consent categories to device mode destinations. This information is sent down the analytics-kotlin SDK and stored for later lookup.
Every event that flows through the library will be stamped with the current status according to whatever configured CMP is used. Event stamping is handled by the ConsentManagementPlugin.
Using consent status stamped on the events and the mappings sent down from the Segment web app each event is evaluated and action is taken. Currently the supported actions are:
- Blocking - This action is implemented by the ConsentBlockingPlugin
Event stamping is the process of adding the consent status information to an existing event. The information is added to the context object of every event. Below is a before and after example:
Before
{
"anonymousId": "23adfd82-aa0f-45a7-a756-24f2a7a4c895",
"type": "track",
"event": "MyEvent",
"userId": "u123",
"timestamp": "2023-01-01T00:00:00.000Z",
"context": {
"traits": {
"email": "peter@example.com",
"phone": "555-555-5555"
},
"device": {
"advertisingId": "7A3CBBA0-BDF5-11E4-8DFC-AA02A5B093DB"
}
}
}
After
{
"anonymousId": "23adfd82-aa0f-45a7-a756-24f2a7a4c895",
"type": "track",
"event": "MyEvent",
"userId": "u123",
"timestamp": "2023-01-01T00:00:00.000Z",
"context": {
"traits": {
"email": "peter@example.com",
"phone": "555-555-5555"
},
"device": {
"advertisingId": "7A3CBBA0-BDF5-11E4-8DFC-AA02A5B093DB"
},
"consent": {
"categoryPreferences": {
"Advertising": true,
"Analytics": false,
"Functional": true,
"DataSharing": false
}
}
}
}
When notified by the CMP SDK that consent has changed, a track event with name “Segment Consent Preference” will be emitted. Below is example of what that event will look like:
{
"anonymousId": "23adfd82-aa0f-45a7-a756-24f2a7a4c895",
"type": "track",
"event": "Segment Consent Preference",
"userId": "u123",
"timestamp": "2023-01-01T00:00:00.000Z",
"context": {
"device": {
"advertisingId": "7A3CBEA0-BDF5-11E4-8DFC-AA07A5B093DB"
},
"consent": {
"categoryPreferences": {
"Advertising": true,
"Analytics": false,
"Functional": true,
"DataSharing": false
}
}
}
}
- An event is dropped onto the timeline by some tracking call.
- The ConsentManagementPlugin consumes the event, stamps it, and returns it.
- The event is now stamped with consent information from this point forward.
- The event is copied. The copy is consumed by a Destination Plugin and continues down its internal timeline. The original event is returned and continues down the main timeline. a. The stamped event is now on the timeline of the destination plugin. b. The event reaches the ConsentBlockingPlugin which makes a decision as to whether or not to let the event continue down the timeline. c. If the event has met the consent requirements it continues down the timeline.
- The event continues down the timeline.
In the Xcode File
menu, click Add Packages
. You'll see a dialog where you can search for Swift packages. In the search field, enter the URL to this repo.
https://github.com/segment-integrations/analytics-swift-consent
You'll then have the option to pin to a version, or specific branch, as well as which project in your workspace to add it to. Once you've made your selections, click the Add Package
button.
Open your Package.swift file and add the following do your the dependencies
section:
.package(
name: "Segment",
url: "https://github.com/segment-integrations/analytics-swift-consent.git",
from: "1.0.0"
),
Next pick from one of the prebuilt integration:
Or build your own integration (see below)
Next you'll need to write some setup/init code where you have your Analytics setup:
let analytics = Analytics(configuration: Configuration(writeKey: "<YOUR WRITE KEY>")
.flushAt(3)
.trackApplicationLifecycleEvents(true))
let consentManager = ConsentManager(provider: MyConsentProvider())
analytics.add(plugin: consentManager)
// add any device mode destinations you might have ...
analytics.add(plugin: FirebaseDestination())
analytics.add(plugin: TaplyticsDestination())
// Note: Different consent management providers may require consentManager.start() be called differently.
// Tell the consent manager to start processing events. It will queue events until start() is called.
consentManager.start()
The Consent Manager plugin will automatically add a ConsentBlockingPlugin to any device mode destinations, so there's no extra steps for you to do in your code. Blocking for cloud mode destinations will be handled server-side at Segment.
In order to integrate a new CMP all you have down is make your own ConsentCategoryProvider object.
You'll need to create a ConsentCategoryProvider
that will provide a mapping of consent category to whether or not a given category has been consented by the user. It must also provide a way to inform the ConsentManager
of any changes that happen during runtime.
Example:
class MyConsentProvider: ConsentCategoryProvider {
// this will be set later by the ConsentManager.
var changeCallback: ConsentChangeCallback? = nil
// this is the imaginary Consent SDK you supplied/wrote.
let consentSDK: MyConsentSDK
var categories: [String : Bool] {
// Returns a simple dictionary of categories and their
// enabled/disabled status.
//
// ie: ["Analytics": true, "Advertising": false, "Performance": true]
return consentSDK.categoriesAndStatus()
}
init(consentSDK: MyConsentSDK) {
self.consentSDK = consentSDK
self.consentSDK.changeListener = consentChanged
}
func consentChanged() {
guard let changeCallback else { return }
// this will tell the ConsentManager that consent has changed, it
// will check the `categories` above again and then send
// a "Segment Consent Preference" track event with the updates.
changeCallback()
}
}
That's all! Enjoy. Feel free to reach out via GitHub Issues, or to Segment support for any additional assitance or questions.
MIT License
Copyright (c) 2023 Segment
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.