LinkMe resolves deep links and passes attribution data (UTM parameters) directly to your app. To view this data in your analytics dashboard (Firebase, PostHog, Mixpanel, etc.), you must manually log the campaign event when a link is received.
[!IMPORTANT] Why is manual logging required? While some analytics SDKs attempt to automatically scrape "direct" deep links from the OS, they cannot detect Deferred Deep Links (links that survive the app install process).
LinkMe fetches deferred data via an API call after your app launches. To attribute these installs correctly, you must take the payload from LinkMe and hand it to your analytics provider.
Prefer server-side streaming?
If you want LinkMe to push events directly to your backend (instead of only SDK-side logging), use the dedicated Webhooks Guide. It covers event subscriptions, delivery history, retries/backoff, and optional request signing.
When to Log
You should log the campaign event in two places to cover all scenarios:
- Cold Start / Install: Inside the
getInitialLinkcallback. - Warm Start: Inside the
addListener(oronLink) callback.

The portal logs mirror what your downstream analytics stack should store—UTM keys, link IDs, and the computed destination—so you can sanity-check payloads before emitting events.
If you are still validating routing before wiring analytics, run the Universal Links Validator, review link analytics, or open the Portal to inspect real click payloads and campaign metadata side by side.
Firebase Analytics (Google Analytics 4)
Official Documentation: Log events
Firebase uses specific parameter names (source, medium, campaign) instead of standard UTM keys (utm_source, etc.). You must map them.
Android (Kotlin)
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.FirebaseAnalytics.Event
import com.google.firebase.analytics.FirebaseAnalytics.Param
fun logToFirebase(payload: LinkPayload) {
val utm = payload.utm ?: return
val bundle = Bundle().apply {
// Standard Firebase Campaign Params
putString(Param.SOURCE, utm["utm_source"])
putString(Param.MEDIUM, utm["utm_medium"])
putString(Param.CAMPAIGN, utm["utm_campaign"])
putString(Param.TERM, utm["utm_term"])
putString(Param.CONTENT, utm["utm_content"])
// Add the LinkMe ID for reference
putString("link_id", payload.linkId)
}
// Log the standard CAMPAIGN_DETAILS event
FirebaseAnalytics.getInstance(context).logEvent(Event.CAMPAIGN_DETAILS, bundle)
}
iOS (Swift)
import FirebaseAnalytics
func logToFirebase(payload: LinkPayload) {
guard let utm = payload.utm else { return }
var params: [String: Any] = [:]
// Map UTM keys to Firebase constants
if let source = utm["utm_source"] { params[AnalyticsParameterSource] = source }
if let medium = utm["utm_medium"] { params[AnalyticsParameterMedium] = medium }
if let campaign = utm["utm_campaign"] { params[AnalyticsParameterCampaign] = campaign }
if let term = utm["utm_term"] { params[AnalyticsParameterTerm] = term }
if let content = utm["utm_content"] { params[AnalyticsParameterContent] = content }
if let linkId = payload.linkId { params["link_id"] = linkId }
// Log the standard campaign_details event
Analytics.logEvent(AnalyticsEventCampaignDetails, parameters: params)
}
PostHog
Official Documentation: Capture events
PostHog accepts standard UTM parameters directly. You can pass them as properties in a Deep Link Opened event or identify the user with them.
// JavaScript / React Native example
posthog.capture('Deep Link Opened', {
$current_url: payload.path,
utm_source: payload.utm?.utm_source,
utm_medium: payload.utm?.utm_medium,
utm_campaign: payload.utm?.utm_campaign,
link_id: payload.linkId
});
Segment
Segment recommends passing campaign data in the context.campaign object.
analytics.track('Deep Link Opened', {
linkId: payload.linkId,
path: payload.path
}, {
campaign: {
name: payload.utm?.utm_campaign,
source: payload.utm?.utm_source,
medium: payload.utm?.utm_medium,
term: payload.utm?.utm_term,
content: payload.utm?.utm_content
}
});
Amplitude
Official Documentation: User Properties
Amplitude recommends tracking UTM parameters as User Properties (for attribution) or Event Properties (for specific campaign interactions).
// Identify user with UTM properties (Attribution)
amplitude.identify(new amplitude.Identify()
.set('utm_source', payload.utm?.utm_source)
.set('utm_medium', payload.utm?.utm_medium)
.set('utm_campaign', payload.utm?.utm_campaign)
);
// Track the open event
amplitude.track('Deep Link Opened', {
link_id: payload.linkId,
...payload.utm // Spread all UTM params as event properties
});
Summary Checklist
- [ ] Map Parameters: Ensure you map
utm_sourcetosourceif your provider requires it (like Firebase). - [ ] Log on Install: Ensure
getInitialLinktriggers the log event so you capture ad-driven installs. - [ ] Log on Open: Ensure
addListenertriggers the log event for re-engagement campaigns. - [ ] Validate the link first: Confirm your AASA or
assetlinks.jsonresponses before debugging analytics payloads.
Need the managed side as well? See pricing for plan details, custom domain setup for branded links, and the Webhooks Guide if you want LinkMe to stream events directly to your backend.