···11package expo.modules.blueskyswissarmy.referrer
2233+import android.content.Intent
44+import android.net.Uri
55+import android.os.Build
36import android.util.Log
47import com.android.installreferrer.api.InstallReferrerClient
58import com.android.installreferrer.api.InstallReferrerStateListener
···811import expo.modules.kotlin.modules.ModuleDefinition
9121013class ExpoBlueskyReferrerModule : Module() {
1414+ private var intent: Intent? = null
1515+ private var activityReferrer: Uri? = null
1616+1117 override fun definition() =
1218 ModuleDefinition {
1319 Name("ExpoBlueskyReferrer")
2020+2121+ OnNewIntent {
2222+ intent = it
2323+ activityReferrer = appContext.currentActivity?.referrer
2424+ }
2525+2626+ AsyncFunction("getReferrerInfoAsync") {
2727+ val intentReferrer =
2828+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
2929+ intent?.getParcelableExtra(Intent.EXTRA_REFERRER, Uri::class.java)
3030+ } else {
3131+ intent?.getParcelableExtra(Intent.EXTRA_REFERRER)
3232+ }
3333+3434+ // Some apps explicitly set a referrer, like Chrome. In these cases, we prefer this since
3535+ // it's the actual website that the user came from rather than the app.
3636+ if (intentReferrer is Uri) {
3737+ val res =
3838+ mapOf(
3939+ "referrer" to intentReferrer.toString(),
4040+ "hostname" to intentReferrer.host,
4141+ )
4242+ intent = null
4343+ return@AsyncFunction res
4444+ }
4545+4646+ // In all other cases, we'll just record the app that sent the intent.
4747+ if (activityReferrer != null) {
4848+ // referrer could become null here. `.toString()` though can be called on null
4949+ val res =
5050+ mapOf(
5151+ "referrer" to activityReferrer.toString(),
5252+ "hostname" to (activityReferrer?.host ?: ""),
5353+ )
5454+ activityReferrer = null
5555+ return@AsyncFunction res
5656+ }
5757+5858+ return@AsyncFunction null
5959+ }
14601561 AsyncFunction("getGooglePlayReferrerInfoAsync") { promise: Promise ->
1662 val referrerClient = InstallReferrerClient.newBuilder(appContext.reactContext).build()
···3131} from 'lib/routes/types'
3232import {RouteParams, State} from 'lib/routes/types'
3333import {bskyTitle} from 'lib/strings/headings'
3434-import {isAndroid, isNative} from 'platform/detection'
3434+import {isAndroid, isNative, isWeb} from 'platform/detection'
3535import {PreferencesExternalEmbeds} from '#/view/screens/PreferencesExternalEmbeds'
3636import {AppPasswords} from 'view/screens/AppPasswords'
3737import {ModerationBlockedAccounts} from 'view/screens/ModerationBlockedAccounts'
···4949 StarterPackScreenShort,
5050} from '#/screens/StarterPack/StarterPackScreen'
5151import {Wizard} from '#/screens/StarterPack/Wizard'
5252+import {Referrer} from '../modules/expo-bluesky-swiss-army'
5253import {init as initAnalytics} from './lib/analytics/analytics'
5354import {useWebScrollRestoration} from './lib/hooks/useWebScrollRestoration'
5455import {attachRouteToLogEvents, logEvent} from './lib/statsig/statsig'
···768769 logEvent('init', {
769770 initMs,
770771 })
772772+773773+ if (isWeb) {
774774+ Referrer.getReferrerInfoAsync().then(info => {
775775+ if (info && info.hostname !== 'bsky.app') {
776776+ logEvent('deepLink:referrerReceived', {
777777+ to: window.location.href,
778778+ referrer: info?.referrer,
779779+ hostname: info?.hostname,
780780+ })
781781+ }
782782+ })
783783+ }
771784772785 if (__DEV__) {
773786 // This log is noisy, so keep false committed
+14-1
src/lib/hooks/useIntentHandler.ts
···11import React from 'react'
22import * as Linking from 'expo-linking'
33+44+import {logEvent} from 'lib/statsig/statsig'
35import {isNative} from 'platform/detection'
66+import {useSession} from 'state/session'
47import {useComposerControls} from 'state/shell'
55-import {useSession} from 'state/session'
68import {useCloseAllActiveElements} from 'state/util'
99+import {Referrer} from '../../../modules/expo-bluesky-swiss-army'
710811type IntentType = 'compose'
912···15181619 React.useEffect(() => {
1720 const handleIncomingURL = (url: string) => {
2121+ Referrer.getReferrerInfoAsync().then(info => {
2222+ if (info && info.hostname !== 'bsky.app') {
2323+ logEvent('deepLink:referrerReceived', {
2424+ to: url,
2525+ referrer: info?.referrer,
2626+ hostname: info?.hostname,
2727+ })
2828+ }
2929+ })
3030+1831 // We want to be able to support bluesky:// deeplinks. It's unnatural for someone to use a deeplink with three
1932 // slashes, like bluesky:///intent/follow. However, supporting just two slashes causes us to have to take care
2033 // of two cases when parsing the url. If we ensure there is a third slash, we can always ensure the first