Skip to content

Commit

Permalink
Merge pull request #12161 from woocommerce/issue/introduce-google-ads…
Browse files Browse the repository at this point in the history
…-cta

[GLA Analytics] Introduce Google Ads CTA into Analytics Hub
  • Loading branch information
ThomazFB authored Jul 29, 2024
2 parents 50f150c + a16f8f1 commit 9f9a9ea
Show file tree
Hide file tree
Showing 17 changed files with 304 additions and 50 deletions.
2 changes: 1 addition & 1 deletion RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*** For entries which are touching the Android Wear app's, start entry with `[WEAR]` too.
19.8
-----

- [*] Stats: The Google Campaign analytics card now has a call to action to create a paid campaign if there are no campaign analytics for the selected time period. [https://github.com/woocommerce/woocommerce-android/pull/12161]

19.7
-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@ class AnalyticsTracker private constructor(
const val VALUE_GOOGLEADS_ENTRY_POINT_SOURCE_MOREMENU = "more_menu"
const val VALUE_GOOGLEADS_ENTRY_POINT_TYPE_CREATION = "creation"
const val VALUE_GOOGLEADS_ENTRY_POINT_TYPE_DASHBOARD = "dashboard"
const val VALUE_GOOGLEADS_ENTRY_POINT_TYPE_ANALYTICS_HUB = "analytics_hub"

var sendUsageStats: Boolean = true
set(value) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package com.woocommerce.android.model

data class GoogleAdsStat(
val googleAdsCampaigns: List<GoogleAdsCampaign>,
val googleAdsCampaigns: List<GoogleAdsCampaign>?,
val totals: GoogleAdsTotals,
val totalsDeltaPercentage: GoogleAdsTotalsDeltaPercentage
) {
val noCampaignsAvailable
get() = googleAdsCampaigns?.isEmpty() ?: false

companion object {
val EMPTY = GoogleAdsStat(
googleAdsCampaigns = emptyList(),
googleAdsCampaigns = null,
totals = GoogleAdsTotals(
sales = 0.0,
spend = 0.0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class GoogleAdsStatUIData(
StatType.TOTAL_SALES -> {
mainTotalStatTitle = resourceProvider.getString(R.string.analytics_google_ads_filter_total_sales)
mainTotalStat = currencyFormatter.formatCurrency(rawStats.totals.sales.toString())
statItems = rawStats.googleAdsCampaigns.map { campaign ->
statItems = rawStats.googleAdsCampaigns?.map { campaign ->
GoogleAdsStatUIDataItem(
name = campaign.name,
mainStat = currencyFormatter.formatCurrency(campaign.subtotal.sales.toString()),
Expand All @@ -32,13 +32,13 @@ class GoogleAdsStatUIData(
currencyFormatter.formatCurrency(campaign.subtotal.spend.toString())
)
)
}
}.orEmpty()
}

StatType.SPEND -> {
mainTotalStatTitle = resourceProvider.getString(R.string.analytics_google_ads_filter_spend)
mainTotalStat = currencyFormatter.formatCurrency(rawStats.totals.spend.toString())
statItems = rawStats.googleAdsCampaigns.map { campaign ->
statItems = rawStats.googleAdsCampaigns?.map { campaign ->
GoogleAdsStatUIDataItem(
name = campaign.name,
mainStat = currencyFormatter.formatCurrency(campaign.subtotal.spend.toString()),
Expand All @@ -47,13 +47,13 @@ class GoogleAdsStatUIData(
currencyFormatter.formatCurrency(campaign.subtotal.sales.toString())
)
)
}
}.orEmpty()
}

StatType.CLICKS -> {
mainTotalStatTitle = resourceProvider.getString(R.string.analytics_google_ads_filter_clicks)
mainTotalStat = rawStats.totals.clicks.toString()
statItems = rawStats.googleAdsCampaigns.map { campaign ->
statItems = rawStats.googleAdsCampaigns?.map { campaign ->
GoogleAdsStatUIDataItem(
name = campaign.name,
mainStat = campaign.subtotal.clicks.toString(),
Expand All @@ -62,13 +62,13 @@ class GoogleAdsStatUIData(
currencyFormatter.formatCurrency(campaign.subtotal.spend.toString())
)
)
}
}.orEmpty()
}

StatType.IMPRESSIONS -> {
mainTotalStatTitle = resourceProvider.getString(R.string.analytics_google_ads_filter_impressions)
mainTotalStat = rawStats.totals.impressions.toString()
statItems = rawStats.googleAdsCampaigns.map { campaign ->
statItems = rawStats.googleAdsCampaigns?.map { campaign ->
GoogleAdsStatUIDataItem(
name = campaign.name,
mainStat = campaign.subtotal.impressions.toString(),
Expand All @@ -77,13 +77,13 @@ class GoogleAdsStatUIData(
currencyFormatter.formatCurrency(campaign.subtotal.spend.toString())
)
)
}
}.orEmpty()
}

StatType.CONVERSIONS -> {
mainTotalStatTitle = resourceProvider.getString(R.string.analytics_google_ads_filter_conversion)
mainTotalStat = rawStats.totals.conversions.toString()
statItems = rawStats.googleAdsCampaigns.map { campaign ->
statItems = rawStats.googleAdsCampaigns?.map { campaign ->
GoogleAdsStatUIDataItem(
name = campaign.name,
mainStat = campaign.subtotal.conversions.toString(),
Expand All @@ -92,7 +92,7 @@ class GoogleAdsStatUIData(
currencyFormatter.formatCurrency(campaign.subtotal.spend.toString())
)
)
}
}.orEmpty()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ sealed class AnalyticsHubListViewState : AnalyticsCardViewState {

sealed class AnalyticsHubCustomSelectionListViewState : AnalyticsCardViewState {
data class LoadingAdsViewState(override val card: AnalyticsCards) : AnalyticsHubCustomSelectionListViewState()

data class NoAdsState(
override val card: AnalyticsCards,
val message: String
) : AnalyticsHubCustomSelectionListViewState()

data class CustomListViewState(
override val card: AnalyticsCards,
val title: String,
Expand All @@ -82,4 +84,26 @@ sealed class AnalyticsHubCustomSelectionListViewState : AnalyticsCardViewState {
else -> "-"
}
}

data class HiddenState(
override val card: AnalyticsCards
) : AnalyticsHubCustomSelectionListViewState()
}

data class AnalyticsHubUserCallToActionViewState(
val title: String,
val description: String,
val callToActionText: String,
val isVisible: Boolean,
val onCallToActionClickListener: () -> Unit
) {
companion object {
val EMPTY = AnalyticsHubUserCallToActionViewState(
title = "",
description = "",
callToActionText = "",
isVisible = false,
onCallToActionClickListener = {}
)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
package com.woocommerce.android.ui.analytics.hub

sealed class AnalyticsHubCardViewState {
data object LoadingCardsConfiguration : AnalyticsHubCardViewState()
data class CardsState(val cardsState: List<AnalyticsCardViewState>) : AnalyticsHubCardViewState()
import com.woocommerce.android.model.AnalyticsCards

sealed class AnalyticsHubCardViewState(
open val cardsState: List<AnalyticsCardViewState>
) {
/**
A default Loading configuration for when the Analytics Hub has started
but the AnalyticCardConfiguration list is still unknown.
*/
data object LoadingCardsConfiguration : AnalyticsHubCardViewState(
cardsState = listOf(
AnalyticsHubInformationViewState.LoadingViewState(AnalyticsCards.Revenue),
AnalyticsHubInformationViewState.LoadingViewState(AnalyticsCards.Orders),
AnalyticsHubListViewState.LoadingViewState(AnalyticsCards.Products),
)
)
data class CardsState(
override val cardsState: List<AnalyticsCardViewState>
) : AnalyticsHubCardViewState(cardsState)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.woocommerce.android.NavGraphMainDirections
import com.woocommerce.android.R
import com.woocommerce.android.databinding.FragmentAnalyticsBinding
import com.woocommerce.android.extensions.handleDialogResult
import com.woocommerce.android.extensions.handleNotice
import com.woocommerce.android.extensions.navigateSafely
import com.woocommerce.android.extensions.scrollStartEvents
import com.woocommerce.android.extensions.showDateRangePicker
Expand All @@ -26,6 +27,9 @@ import com.woocommerce.android.ui.analytics.ranges.StatsTimeRangeSelection.Selec
import com.woocommerce.android.ui.base.BaseFragment
import com.woocommerce.android.ui.common.MarginBottomItemDecoration
import com.woocommerce.android.ui.feedback.SurveyType
import com.woocommerce.android.ui.google.webview.GoogleAdsWebViewFragment.Companion.WEBVIEW_RESULT
import com.woocommerce.android.ui.google.webview.GoogleAdsWebViewViewModel.EntryPointSource.ANALYTICS_HUB
import com.woocommerce.android.ui.google.webview.GoogleAdsWebViewViewModel.UrlComparisonMode.PARTIAL
import com.woocommerce.android.util.ChromeCustomTabUtils
import com.woocommerce.android.viewmodel.MultiLiveEvent
import dagger.hilt.android.AndroidEntryPoint
Expand Down Expand Up @@ -81,6 +85,12 @@ class AnalyticsHubFragment : BaseFragment(R.layout.fragment_analytics) {

private fun handleEvent(event: MultiLiveEvent.Event) {
when (event) {
is AnalyticsViewEvent.OpenGoogleAdsCreation -> startGoogleAdsWebView(
url = event.url,
title = event.title,
isCreationFlow = event.isCreationFlow
)

is AnalyticsViewEvent.OpenUrl -> ChromeCustomTabUtils.launchUrl(requireContext(), event.url)

is AnalyticsViewEvent.OpenWPComWebView -> findNavController()
Expand Down Expand Up @@ -124,6 +134,13 @@ class AnalyticsHubFragment : BaseFragment(R.layout.fragment_analytics) {
?.let { viewModel.onNewRangeSelection(it) }
?: viewModel.onCustomDateRangeClicked()
}

handleNotice(WEBVIEW_RESULT) {
viewModel.onRefreshRequested()
findNavController().navigateSafely(
NavGraphMainDirections.actionGlobalGoogleAdsCampaignSuccessBottomSheet()
)
}
}

private fun bind(view: View) {
Expand All @@ -145,15 +162,13 @@ class AnalyticsHubFragment : BaseFragment(R.layout.fragment_analytics) {
binding.analyticsDateSelectorCard.updatePreviousRange(viewState.analyticsDateRangeSelectorState.previousRange)
binding.analyticsDateSelectorCard.updateCurrentRange(viewState.analyticsDateRangeSelectorState.currentRange)
binding.analyticsDateSelectorCard.updateLastUpdateTimestamp(viewState.lastUpdateTimestamp)
when (viewState.cards) {
is AnalyticsHubCardViewState.CardsState -> {
(binding.cards.adapter as AnalyticsHubCardsAdapter).cardList = viewState.cards.cardsState
}

else -> {}
}
binding.analyticsCallToActionCard.updateInformation(viewState.ctaState)
binding.analyticsRefreshLayout.isRefreshing = viewState.refreshIndicator == ShowIndicator
displayFeedbackBanner(viewState.showFeedBackBanner)

binding.cards.adapter
.run { this as? AnalyticsHubCardsAdapter }
?.cardList = viewState.cards.cardsState
}

private fun getDateRangeSelectorViewState() = viewModel.viewState.value.analyticsDateRangeSelectorState
Expand Down Expand Up @@ -193,4 +208,20 @@ class AnalyticsHubFragment : BaseFragment(R.layout.fragment_analytics) {
Lifecycle.State.RESUMED
)
}

private fun startGoogleAdsWebView(
url: String,
title: String,
isCreationFlow: Boolean
) {
val direction = NavGraphMainDirections.actionGlobalGoogleAdsWebViewFragment(
urlToLoad = url,
title = title,
urlComparisonMode = PARTIAL,
isCreationFlow = isCreationFlow,
entryPointSource = ANALYTICS_HUB
)

findNavController().navigateSafely(direction)
}
}
Loading

0 comments on commit 9f9a9ea

Please sign in to comment.