Advanced usage
User ID
The user ID lets you associate events from various sources with the same user. Each new visitor gets a randomly generated visitor ID that the SDK keeps between app launches. With the user ID you can replace this random identifier with your own - for example an email address or an ID from your CRM.
Use the userID property to set the user ID:
PiwikTracker.sharedInstance()?.userID = "John Doe"[PiwikTracker sharedInstance].userID = @"John Doe";- Use a non-empty string when you set a user ID; pass
nil(or leave unset) so the SDK does not send one. The property itself is optional on the tracker.
The user ID is not sent if data anonymization is enabled (isAnonymizationEnabled = YES).
User email address
DeprecatedThe user email address property
userEmailwas used by Audience Manager. Audience Manager is no longer available in the latest product version. Use the user ID for cross-source identity instead.
Device ID
DeprecatedThe
deviceIDproperty is no longer recommended. Audience Manager is no longer available in the latest product version, and the value is only forwarded on Audience Manager requests.
By default the device ID is empty (nil). You can set a non-empty string with the property (for example IDFA from Ad Support):
import AdSupport
let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
PiwikTracker.sharedInstance()?.deviceID = idfa#import <AdSupport/ASIdentifierManager.h>
NSString *idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
[PiwikTracker sharedInstance].deviceID = idfa;The device ID is not sent if data anonymization is enabled.
Visitor ID
To track user sessions across different sources, the SDK uses the visitor ID. The visitor ID is randomly generated when the tracker instance is created and is stored between application launches. You can set the visitor ID manually using setVisitorID(newVisitorID:):
PiwikTracker.sharedInstance()?.setVisitorID(newVisitorID: "0123456789abcdef")[[PiwikTracker sharedInstance] setVisitorID:@"0123456789abcdef"];- For
setVisitorID, the ID must be exactly 16 characters: lowercase hexadecimal0-9a-fonly. Invalid input leaves the stored visitor ID unchanged.
When anonymization is enabled, the SDK issues a new visitor ID when it first needs one in an app run (and persists it). Every unique visitor must be assigned a different ID, and that ID must not change after assignment. We recommend using the user ID rather than the visitor ID to identify users.
You can also limit how long the current visitor ID remains valid with visitorIDLifetime (seconds). When it expires, the SDK assigns a new random visitor ID and clears visit-scoped data (for example default visit custom variables, custom dimensions, campaign parameters). Use 0 or less for no expiry (default).
PiwikTracker.sharedInstance()?.visitorIDLifetime = 30 * 24 * 60 * 60[PiwikTracker sharedInstance].visitorIDLifetime = 30 * 24 * 60 * 60;Sessions
A session represents a set of user interactions with your app. By default, the SDK starts a new session when more than 30 minutes pass without any queued analytics event. Only interactions that reach the local queue extend the session: with optOut enabled nothing is queued, and with sampleRate below 100 some calls may be dropped before queuing, so the timer does not advance in those cases. You can change the timeout with sessionTimeout:
PiwikTracker.sharedInstance()?.sessionTimeout = 30 * 60[PiwikTracker sharedInstance].sessionTimeout = 30 * 60;- The timeout (required) is a session timeout time in seconds.
You can manually start a new session with startNewSession(). The no-argument call drops visit-level data you set on the tracker (for example visit custom variables). To keep that data, use startNewSession(preserveSessionParameters: true):
PiwikTracker.sharedInstance()?.startNewSession()
PiwikTracker.sharedInstance()?.startNewSession(preserveSessionParameters: true)[[PiwikTracker sharedInstance] startNewSession];
[[PiwikTracker sharedInstance] startNewSession:YES];Dispatching
Tracked events are stored temporarily on the queue and by default dispatched in batches every 30 seconds. You can change this behavior with dispatchInterval:
dispatchInterval = 0- incoming events are dispatched immediately.dispatchInterval = -1- incoming events are not dispatched automatically. You can then trigger a manual dispatch withdispatch().
PiwikTracker.sharedInstance()?.dispatchInterval = -1
do {
try processCart()
} catch {
PiwikTracker.sharedInstance()?.sendException(description: error.localizedDescription)
PiwikTracker.sharedInstance()?.dispatch()
}[PiwikTracker sharedInstance].dispatchInterval = -1;
@try {
[self processCart];
}
@catch (NSException *exception) {
[[PiwikTracker sharedInstance] sendExceptionWithDescription:exception.reason];
[[PiwikTracker sharedInstance] dispatch];
}When more than one event is queued, the SDK sends them in bulk using POST requests with a JSON payload. One call to dispatch() can still use several HTTP requests when the backlog is larger than eventsPerRequest allows for a single request.
To drop everything that is currently queued without sending it, use deleteQueuedEvents().
Default custom variables
The SDK can automatically populate platform name, OS version and app version into visit-scoped custom variables with indexes 1-3. By default this option is on. Toggle it with includeDefaultCustomVariable:
PiwikTracker.sharedInstance()?.includeDefaultCustomVariable = false[PiwikTracker sharedInstance].includeDefaultCustomVariable = NO;If you need to use indexes 1-3 yourself, turn this option off and set custom variables manually with setCustomVariable (legacy) or use the recommended setCustomDimension.
App name and app version
By default the SDK reads the app name from CFBundleDisplayName (or CFBundleName as a fallback) and builds the version string from CFBundleShortVersionString and CFBundleVersion (formatted like the App version custom variable). You can override either with appName and appVersion:
PiwikTracker.sharedInstance()?.appName = "MyApp Beta"
PiwikTracker.sharedInstance()?.appVersion = "2.5.0-beta+build.123"[PiwikTracker sharedInstance].appName = @"MyApp Beta";
[PiwikTracker sharedInstance].appVersion = @"2.5.0-beta+build.123";Local storage limits
You can set limits on how long and how many events are kept in local storage. Events older than the limit are discarded on the next dispatch attempt. The Piwik backend accepts back-dated events for up to 24 hours by default.
To change the maximum age of queued events, use maxAgeOfQueuedEvents:
PiwikTracker.sharedInstance()?.maxAgeOfQueuedEvents = 12 * 60 * 60[PiwikTracker sharedInstance].maxAgeOfQueuedEvents = 12 * 60 * 60;To change the maximum number of queued events, use maxNumberOfQueuedEvents. The default is 500. Setting the limit to 0 stops new events from being queued.
PiwikTracker.sharedInstance()?.maxNumberOfQueuedEvents = 250[PiwikTracker sharedInstance].maxNumberOfQueuedEvents = 250;Anonymization
When anonymization is on, the user's IP address, location (only the country is reported), user ID and device ID are not collected. The SDK generates a new visitor ID each time the application starts (when it first needs one in that run). The default value is YES.
PiwikTracker.sharedInstance()?.isAnonymizationEnabled = false[PiwikTracker sharedInstance].isAnonymizationEnabled = NO;Opt-out
When optOut is true, the SDK does not store new analytics events. The flag defaults to false and is persisted across app restarts and upgrades.
Events already in the queue before opt-out can still be uploaded if you call dispatch(). To drop them without sending, use deleteQueuedEvents().
PiwikTracker.sharedInstance()?.optOut = true[PiwikTracker sharedInstance].optOut = YES;Dry run
dryRun is useful during development. Instead of sending events to the Piwik server, the SDK prints them to the console.
PiwikTracker.sharedInstance()?.dryRun = true[PiwikTracker sharedInstance].dryRun = YES;Sample rate
If your app generates a lot of Analytics traffic, you can configure client-side sampling with sampleRate. The value is a whole number from 1 to 100; roughly sampleRate / 100 of Analytics events are kept (the fraction is approximate). Default: 100 (no sampling).
PiwikTracker.sharedInstance()?.sampleRate = 10[PiwikTracker sharedInstance].sampleRate = 10;URL prefixing
When isPrefixingEnabled is true (default), sendView() and sendViews() prepend the screen segment to the path you pass (for example settings becomes screen/settings). Other tracking APIs are not governed by this flag. Turn prefixing off if you want only the path strings you supply:
PiwikTracker.sharedInstance()?.isPrefixingEnabled = false[PiwikTracker sharedInstance].isPrefixingEnabled = NO;Using the SDK with SwiftUI
The SDK works with both UIKit (UIApplicationDelegate) and SwiftUI (App protocol) lifecycles. This section covers the patterns you need when using the SwiftUI lifecycle (the default for new Xcode projects since iOS 14).
Initializing the tracker
The simplest place to configure the tracker is the App initializer. It runs once before any Scene or view is created:
import SwiftUI
import PiwikPROSDK
@main
struct MyApp: App {
init() {
PiwikTracker.sharedInstance(
siteID: "site-id",
baseURL: URL(string: "https://example.piwik.pro")!
)
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}If you need standard UIApplicationDelegate callbacks, attach a small AppDelegate using @UIApplicationDelegateAdaptor - see the landing page for the full example.
Tracking screen views with .onAppear
.onAppearCall sendView() from the .onAppear modifier when the view appears. In a UIKit UIViewController, call it from viewDidAppear instead:
struct ContentView: View {
var body: some View {
VStack {
Text("Hello, world!")
}
.onAppear {
PiwikTracker.sharedInstance()?.sendView(view: "Home")
}
}
}Reusable view modifier
If you track screen views from many views, define a small modifier so each call site stays a single line:
extension View {
func trackPiwikView(_ name: String) -> some View {
onAppear {
PiwikTracker.sharedInstance()?.sendView(view: name)
}
}
}
struct SettingsView: View {
var body: some View {
Form {
// ...
}
.trackPiwikView("Settings")
}
}Handling deep links with .onOpenURL
.onOpenURLAttach the .onOpenURL modifier to attribute incoming URLs to web sessions or pass campaign data. In a UIKit app delegate, handle the same URLs in application(_:open:options:). sendCampaign() does not send an event by itself: campaign parameters are stored and attached to the next analytics event the SDK sends, then cleared.
@main
struct MyApp: App {
init() {
PiwikTracker.sharedInstance(
siteID: "site-id",
baseURL: URL(string: "https://example.piwik.pro")!
)
}
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL { url in
// Cross-platform tracking: pick up pk_vid from the deep link
PiwikTracker.sharedInstance()?.setVisitorIdFrom(url: url)
// Campaign attribution: capture pk_campaign / pk_keyword
PiwikTracker.sharedInstance()?.sendCampaign(url: url.absoluteString)
}
}
}
}See Cross-platform tracking for more about pk_vid and sendCampaign() for campaign URL parameters.
Tracking app installs and updates
Call the lifecycle methods from App.init() (or from the AppDelegate adapter, if you use one). applicationInstall() runs at most once per app installation on the device (first launch after install; a reinstall can send it again). applicationUpdate() runs at most once per distinct bundle version (CFBundleShortVersionString + CFBundleVersion).
@main
struct MyApp: App {
init() {
PiwikTracker.sharedInstance(
siteID: "site-id",
baseURL: URL(string: "https://example.piwik.pro")!
)
PiwikTracker.sharedInstance()?.applicationInstall()
PiwikTracker.sharedInstance()?.applicationUpdate()
}
var body: some Scene {
WindowGroup { ContentView() }
}
}Updated 3 days ago