Skip to content

Commit eef6a89

Browse files
authored
Merge pull request #19512 from wordpress-mobile/task/adds_store_link_referrer
Adds referrer information when opening a Google Play store link
2 parents a5d90e5 + 6c58bb3 commit eef6a89

7 files changed

Lines changed: 58 additions & 7 deletions

File tree

WordPress/src/main/java/org/wordpress/android/ui/ActivityLauncherWrapper.kt

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import org.wordpress.android.R
1111
import org.wordpress.android.fluxc.model.PostImmutableModel
1212
import org.wordpress.android.fluxc.model.SiteModel
1313
import org.wordpress.android.ui.posts.RemotePreviewLogicHelper.RemotePreviewType
14+
import org.wordpress.android.util.UrlUtils
1415
import javax.inject.Inject
1516

1617
/**
@@ -36,13 +37,13 @@ class ActivityLauncherWrapper @Inject constructor() {
3637
) = ActivityLauncher.previewPostOrPageForResult(activity, site, post, remotePreviewType)
3738

3839
@Suppress("SwallowedException")
39-
fun openPlayStoreLink(activity: Activity, packageName: String) {
40+
fun openPlayStoreLink(activity: Activity, packageName: String, utmCampaign: String? = null) {
4041
var intent: Intent? = activity.packageManager.getLaunchIntentForPackage(packageName)
4142
val isAppAlreadyInstalled = intent != null
4243

4344
if (intent == null) {
4445
intent = Intent(Intent.ACTION_VIEW).apply {
45-
data = Uri.parse("https://play.google.com/store/apps/details?id=$packageName")
46+
data = Uri.parse(getPlayStoreUrl(activity.application.packageName, packageName, utmCampaign))
4647
flags = Intent.FLAG_ACTIVITY_NEW_TASK
4748
setPackage("com.android.vending")
4849
}
@@ -60,6 +61,15 @@ class ActivityLauncherWrapper @Inject constructor() {
6061
}
6162
}
6263

64+
fun getPlayStoreUrl(appPackageName: String, destinationPackageName: String, utmCampaign: String? = null): String {
65+
val referrer = utmCampaign?.let {
66+
val encoded = UrlUtils.urlEncode("$GOOGLE_STORE_UTM_SOURCE=$appPackageName&$GOOGLE_STORE_UTM_CAMPAIGN=$it")
67+
"$GOOGLE_STORE_REFERRER=$encoded"
68+
}
69+
val storeUrl = "$GOOGLE_STORE_URL_APP_DETAILS?$GOOGLE_STORE_URL_APP_ID=$destinationPackageName"
70+
return referrer?.let { "$storeUrl&$it" } ?: storeUrl
71+
}
72+
6373
private fun preventBackNavigation(activity: Activity, shouldPrevent: Boolean) {
6474
if (shouldPrevent) {
6575
activity.finishAffinity()
@@ -68,5 +78,15 @@ class ActivityLauncherWrapper @Inject constructor() {
6878

6979
companion object {
7080
const val JETPACK_PACKAGE_NAME = "com.jetpack.android"
81+
const val GOOGLE_STORE_URL_APP_DETAILS = "https://play.google.com/store/apps/details"
82+
const val GOOGLE_STORE_URL_APP_ID = "id"
83+
const val GOOGLE_STORE_REFERRER = "referrer"
84+
const val GOOGLE_STORE_UTM_SOURCE = "utm_source"
85+
const val GOOGLE_STORE_UTM_CAMPAIGN = "utm_campaign"
86+
const val CAMPAIGN_SITE_CREATION = "site_creation"
87+
const val CAMPAIGN_BOTTOM_SHEET = "bottom_sheet"
88+
const val CAMPAIGN_STATIC_POSTER = "static_poster"
89+
const val CAMPAIGN_INDIVIDUAL_PLUGIN = "individual_plugin"
90+
const val CAMPAIGN_JETPACK_OVERLAY = "jetpack_overlay"
7191
}
7292
}

WordPress/src/main/java/org/wordpress/android/ui/jetpackoverlay/JetpackFeatureFullScreenOverlayFragment.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
1010
import dagger.hilt.android.AndroidEntryPoint
1111
import org.wordpress.android.databinding.JetpackFeatureRemovalOverlayBinding
1212
import org.wordpress.android.ui.ActivityLauncherWrapper
13+
import org.wordpress.android.ui.ActivityLauncherWrapper.Companion.CAMPAIGN_JETPACK_OVERLAY
1314
import org.wordpress.android.ui.ActivityLauncherWrapper.Companion.JETPACK_PACKAGE_NAME
1415
import org.wordpress.android.ui.WPWebViewActivity
1516
import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureOverlayActions.DismissDialog
@@ -93,7 +94,7 @@ class JetpackFeatureFullScreenOverlayFragment : BottomSheetDialogFragment() {
9394
is OpenPlayStore -> {
9495
dismiss()
9596
activity?.let {
96-
activityLauncherWrapper.openPlayStoreLink(it, JETPACK_PACKAGE_NAME)
97+
activityLauncherWrapper.openPlayStoreLink(it, JETPACK_PACKAGE_NAME, CAMPAIGN_JETPACK_OVERLAY)
9798
}
9899
}
99100
is DismissDialog -> {

WordPress/src/main/java/org/wordpress/android/ui/jetpackoverlay/individualplugin/WPJetpackIndividualPluginFragment.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ class WPJetpackIndividualPluginFragment : BottomSheetDialogFragment() {
8181
when (actionEvent) {
8282
is ActionEvent.PrimaryButtonClick -> activityLauncher.openPlayStoreLink(
8383
requireActivity(),
84-
ActivityLauncherWrapper.JETPACK_PACKAGE_NAME
84+
ActivityLauncherWrapper.JETPACK_PACKAGE_NAME,
85+
ActivityLauncherWrapper.CAMPAIGN_INDIVIDUAL_PLUGIN
8586
)
8687

8788
is ActionEvent.Dismiss -> dismiss()

WordPress/src/main/java/org/wordpress/android/ui/main/jetpack/staticposter/JetpackStaticPosterFragment.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import androidx.fragment.app.Fragment
1212
import androidx.fragment.app.viewModels
1313
import dagger.hilt.android.AndroidEntryPoint
1414
import org.wordpress.android.ui.ActivityLauncherWrapper
15+
import org.wordpress.android.ui.ActivityLauncherWrapper.Companion.CAMPAIGN_STATIC_POSTER
1516
import org.wordpress.android.ui.ActivityLauncherWrapper.Companion.JETPACK_PACKAGE_NAME
1617
import org.wordpress.android.ui.WPWebViewActivity
1718
import org.wordpress.android.ui.compose.theme.AppTheme
@@ -59,7 +60,8 @@ class JetpackStaticPosterFragment : Fragment() {
5960
when (event) {
6061
is Event.PrimaryButtonClick -> activityLauncher.openPlayStoreLink(
6162
requireActivity(),
62-
JETPACK_PACKAGE_NAME
63+
JETPACK_PACKAGE_NAME,
64+
CAMPAIGN_STATIC_POSTER
6365
)
6466
is Event.SecondaryButtonClick -> event.url?.let {
6567
WPWebViewActivity.openURL(requireContext(), UrlUtils.addUrlSchemeIfNeeded(it, true))

WordPress/src/main/java/org/wordpress/android/ui/mysite/jetpackbadge/JetpackPoweredBottomSheetFragment.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import org.wordpress.android.R
1717
import org.wordpress.android.databinding.JetpackPoweredBottomSheetBinding
1818
import org.wordpress.android.databinding.JetpackPoweredExpandedBottomSheetBinding
1919
import org.wordpress.android.ui.ActivityLauncherWrapper
20+
import org.wordpress.android.ui.ActivityLauncherWrapper.Companion.CAMPAIGN_BOTTOM_SHEET
2021
import org.wordpress.android.ui.ActivityLauncherWrapper.Companion.JETPACK_PACKAGE_NAME
2122
import org.wordpress.android.ui.main.WPMainNavigationView.PageType
2223
import org.wordpress.android.ui.main.WPMainNavigationView.PageType.ME
@@ -130,7 +131,7 @@ class JetpackPoweredBottomSheetFragment : BottomSheetDialogFragment() {
130131
is OpenPlayStore -> {
131132
dismiss()
132133
activity?.let {
133-
activityLauncherWrapper.openPlayStoreLink(it, JETPACK_PACKAGE_NAME)
134+
activityLauncherWrapper.openPlayStoreLink(it, JETPACK_PACKAGE_NAME, CAMPAIGN_BOTTOM_SHEET)
134135
}
135136
}
136137
is DismissDialog -> {

WordPress/src/main/java/org/wordpress/android/ui/sitecreation/SiteCreationActivity.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import org.wordpress.android.BuildConfig
1414
import org.wordpress.android.R
1515
import org.wordpress.android.ui.ActivityLauncher
1616
import org.wordpress.android.ui.ActivityLauncherWrapper
17+
import org.wordpress.android.ui.ActivityLauncherWrapper.Companion.CAMPAIGN_SITE_CREATION
1718
import org.wordpress.android.ui.ActivityLauncherWrapper.Companion.JETPACK_PACKAGE_NAME
1819
import org.wordpress.android.ui.LocaleAwareActivity
1920
import org.wordpress.android.ui.accounts.HelpActivity.Origin
@@ -188,7 +189,7 @@ class SiteCreationActivity : LocaleAwareActivity(),
188189
when (action) {
189190
is OpenPlayStore -> {
190191
fragment.dismiss()
191-
activityLauncherWrapper.openPlayStoreLink(this, JETPACK_PACKAGE_NAME)
192+
activityLauncherWrapper.openPlayStoreLink(this, JETPACK_PACKAGE_NAME, CAMPAIGN_SITE_CREATION)
192193
}
193194
is DismissDialog -> {
194195
fragment.dismiss()

WordPress/src/test/java/org/wordpress/android/ui/ActivityLauncherWrapperTest.kt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package org.wordpress.android.ui
22

33
import android.app.Activity
4+
import android.app.Application
45
import android.content.pm.PackageManager
56
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
7+
import org.assertj.core.api.Assertions.assertThat
68
import org.junit.Before
79
import org.junit.Rule
810
import org.junit.Test
@@ -45,16 +47,39 @@ class ActivityLauncherWrapperTest {
4547
verify(activity).finishAffinity()
4648
}
4749

50+
@Test
51+
fun `when a campaign is passed the store url includes a referrer`() {
52+
val expectedStoreUrl = "https://play.google.com/store/apps/details?id=com.jetpack.android" +
53+
"&referrer=utm_source%3Dorg.wordpress.android%26utm_campaign%3Dtest_campaign"
54+
val actualStoreUrl = classToTest.getPlayStoreUrl(SOURCE_PACKAGE, TARGET_PACKAGE, TEST_CAMPAIGN)
55+
assertThat(actualStoreUrl).isEqualTo(expectedStoreUrl)
56+
}
57+
58+
@Test
59+
fun `when a campaign is not passed the store url does not include a referrer`() {
60+
val expectedStoreUrl = "https://play.google.com/store/apps/details?id=com.jetpack.android"
61+
val actualStoreUrl = classToTest.getPlayStoreUrl(SOURCE_PACKAGE, TARGET_PACKAGE)
62+
assertThat(actualStoreUrl).isEqualTo(expectedStoreUrl)
63+
}
4864

4965
private fun mockAppPreinstalled(isInstalled: Boolean): Activity {
5066
val activity = mock<Activity>()
67+
val application = mock<Application>()
5168
val packageManager = mock<PackageManager>()
5269
whenever(activity.packageManager).thenReturn(packageManager)
70+
whenever(activity.application).thenReturn(application)
71+
whenever(application.packageName).thenReturn(SOURCE_PACKAGE)
5372

5473
if (isInstalled) {
5574
whenever(packageManager.getLaunchIntentForPackage(any())).thenReturn(mock())
5675
}
5776

5877
return activity
5978
}
79+
80+
companion object {
81+
const val SOURCE_PACKAGE = "org.wordpress.android"
82+
const val TARGET_PACKAGE = "com.jetpack.android"
83+
const val TEST_CAMPAIGN = "test_campaign"
84+
}
6085
}

0 commit comments

Comments
 (0)