Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chore] 데이터 태깅 / 앰플리튜드 설정하기 #166

Merged
merged 20 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
551b2f9
[chore] #147 앰플리튜드 디펜던시 추가, 관련 권한 부여
leeeha Aug 28, 2023
9a11ea7
[chore] #147 앰플리튜드 클라이언트 객체 초기화
leeeha Aug 28, 2023
91239ff
[feat] #147 앱 사용 가이드 화면 데이터 태깅 작업
leeeha Aug 28, 2023
f7c8dfc
[feat] #147 회원가입 화면 데이터 태깅
leeeha Aug 28, 2023
2b98896
[fix] #147 page_number 대신에 paging_number 네이밍 사용하도록 변경
leeeha Aug 28, 2023
2b643a1
[feat] #147 닉네임 화면 데이터 태깅
leeeha Aug 28, 2023
42ec41a
[feat] #147 위니피드 뷰 이벤트 데이터 태깅
leeeha Aug 28, 2023
fe7a5c1
Merge branch 'develop' of https://github.com/team-winey/Winey-AOS int…
leeeha Aug 28, 2023
2322dd0
[feat] #147 위니피드 아이템 클릭, 좋아요/취소, 업로드 버튼 클릭에 대한 태깅 작업
leeeha Aug 28, 2023
a2550ef
[feat] #147 상세 피드 데이터 태깅
leeeha Aug 28, 2023
5b7cd6b
[feat] #147 위니피드 목표 설정 다이얼로그 이벤트 태깅
leeeha Aug 28, 2023
9497dda
[feat] #147 목표설정 바텀시트 뷰 이벤트 태깅
leeeha Aug 28, 2023
49d0a14
[feat] #147 마이페이지 이벤트 태깅
leeeha Aug 28, 2023
e4cfd69
[feat] #147 추천피드 이벤트 태깅
leeeha Aug 28, 2023
4a6ebf9
[feat] #147 위니 업로드 이벤트 태깅
leeeha Aug 28, 2023
197fa98
[fix] #147 앱 사용 가이드 화면 뷰 이벤트 네이밍 변경
leeeha Aug 28, 2023
3954800
Merge branch 'develop' of https://github.com/team-winey/Winey-AOS int…
leeeha Aug 28, 2023
edd11e2
[fix] #147 PR Checker yml 파일에 앰플리튜드 api key 추가
leeeha Aug 28, 2023
e14b2a9
[fix] #147 PR Checker yml 파일에 앰플리튜드 api key 추가
leeeha Aug 28, 2023
ccffa67
Merge remote-tracking branch 'origin/feature/chore-set-amplitude' int…
leeeha Aug 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/pr_checker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ jobs:
env:
AUTH_BASE_URL: ${{ secrets.AUTH_BASE_URL }}
KAKAO_NATIVE_KEY: ${{ secrets.KAKAO_NATIVE_KEY }}
AMPLITUDE_API_KEY: ${{ secrets.AMPLITUDE_API_KEY }}
run: |
echo auth.base.url=\"$AUTH_BASE_URL\" >> ./local.properties
echo kakao.native.key=\"$KAKAO_NATIVE_KEY\" >> ./local.properties
echo kakaoNativeKey=$KAKAO_NATIVE_KEY >> ./local.properties
echo amplitude.api.key=\"AMPLITUDE_API_KEY\" >> ./local.properties

# - name: Access Firebase Service
# run: echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > ./app/google-services.json
Expand Down
6 changes: 6 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ android {
"KAKAO_NATIVE_KEY",
gradleLocalProperties(rootDir).getProperty("kakao.native.key")
)
buildConfigField(
"String",
"AMPLITUDE_API_KEY",
gradleLocalProperties(rootDir).getProperty("amplitude.api.key")
)

manifestPlaceholders["KAKAO_NATIVE_KEY"] = gradleLocalProperties(rootDir).getProperty("kakaoNativeKey")

Expand Down Expand Up @@ -122,6 +127,7 @@ dependencies {
implementation(lottie)
implementation(circleImageView)
implementation(kakaoLogin)
implementation(amplitude)

debugImplementation(flipper)
debugImplementation(flipperNetwork)
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

<application
android:name=".WineyApplication"
Expand Down
26 changes: 26 additions & 0 deletions app/src/main/java/com/android/go/sopt/winey/di/AmplitudeModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.android.go.sopt.winey.di

import android.app.Application
import android.content.Context
import com.amplitude.api.Amplitude
import com.amplitude.api.AmplitudeClient
import com.android.go.sopt.winey.BuildConfig
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object AmplitudeModule {
@Provides
@Singleton
fun provideAmplitudeClient(
@ApplicationContext context: Context,
application: Application
): AmplitudeClient = Amplitude.getInstance()
.initialize(context, BuildConfig.AMPLITUDE_API_KEY)
.enableForegroundTracking(application)
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,16 @@ class WineyFeedAdapter(
holder.onBind(getItem(position))
}

fun updateItem(feedId: Int, isLiked: Boolean, likes: Int) {
fun updateItem(feedId: Int, isLiked: Boolean, likes: Int): WineyFeed? {
snapshot().items.forEachIndexed { index, wineyFeed ->
if (wineyFeed.feedId == feedId) {
wineyFeed.isLiked = isLiked
wineyFeed.likes = likes.toLong()
notifyItemChanged(index)
return wineyFeed
}
}
return null
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ import com.android.go.sopt.winey.presentation.main.feed.detail.DetailActivity
import com.android.go.sopt.winey.presentation.main.feed.upload.UploadActivity
import com.android.go.sopt.winey.presentation.main.mypage.MyPageFragment
import com.android.go.sopt.winey.presentation.main.notification.NotificationActivity
import com.android.go.sopt.winey.util.amplitude.AmplitudeUtils
import com.android.go.sopt.winey.util.amplitude.type.EventType
import com.android.go.sopt.winey.util.amplitude.type.EventType.TYPE_CLICK_FEED_ITEM
import com.android.go.sopt.winey.util.amplitude.type.EventType.TYPE_CLICK_LIKE
import com.android.go.sopt.winey.util.binding.BindingFragment
import com.android.go.sopt.winey.util.fragment.WineyDialogFragment
import com.android.go.sopt.winey.util.fragment.snackBar
Expand All @@ -46,6 +50,8 @@ import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.json.JSONException
import org.json.JSONObject
import timber.log.Timber
import javax.inject.Inject

Expand All @@ -63,17 +69,23 @@ class WineyFeedFragment :
@Inject
lateinit var dataStoreRepository: DataStoreRepository

@Inject
lateinit var amplitudeUtils: AmplitudeUtils

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
removeRecyclerviewItemChangeAnimation()
amplitudeUtils.logEvent("view_homefeed")

binding.vm = mainViewModel
mainViewModel.getHasNewNoti()

initAdapter()
setSwipeRefreshListener()
initFabClickListener()
initGetFeedStateObserver()
initPostLikeStateObserver()
initNotificationButtonClickListener()
removeRecyclerviewItemChangeAnimation()
}

override fun onStart() {
Expand Down Expand Up @@ -106,7 +118,10 @@ class WineyFeedFragment :
onPopupMenuClicked = { anchorView, wineyFeed ->
showFeedPopupMenu(anchorView, wineyFeed)
},
toFeedDetail = { wineyFeed -> navigateToDetail(wineyFeed) }
toFeedDetail = { wineyFeed ->
sendWineyFeedEvent(TYPE_CLICK_FEED_ITEM, wineyFeed)
navigateToDetail(wineyFeed)
}
)
binding.rvWineyfeedPost.adapter = ConcatAdapter(
wineyFeedHeaderAdapter,
Expand Down Expand Up @@ -247,11 +262,13 @@ class WineyFeedFragment :
viewModel.postWineyFeedLikeState.flowWithLifecycle(viewLifeCycle).onEach { state ->
when (state) {
is UiState.Success -> {
wineyFeedAdapter.updateItem(
val item = wineyFeedAdapter.updateItem(
state.data.data.feedId,
state.data.data.isLiked,
state.data.data.likes
)
) ?: return@onEach

sendWineyFeedEvent(TYPE_CLICK_LIKE, item)
}

is UiState.Failure -> {
Expand All @@ -265,6 +282,7 @@ class WineyFeedFragment :

private fun initFabClickListener() {
binding.btnWineyfeedFloating.setOnSingleClickListener {
amplitudeUtils.logEvent("click_write_contents")
initGetUserStateObserver()
}
}
Expand Down Expand Up @@ -298,20 +316,48 @@ class WineyFeedFragment :

private fun isGoalValid(data: User?) {
if (data?.isOver == true) {
val dialog = WineyDialogFragment(
stringOf(R.string.wineyfeed_goal_dialog_title),
stringOf(R.string.wineyfeed_goal_dialog_subtitle),
stringOf(R.string.wineyfeed_goal_dialog_negative_button),
stringOf(R.string.wineyfeed_goal_dialog_positive_button),
handleNegativeButton = {},
handlePositiveButton = { navigateTo<MyPageFragment>() }
)
dialog.show(parentFragmentManager, TAG_GOAL_DIALOG)
showGoalSettingDialog()
} else {
navigateToUpload()
}
}

private fun showGoalSettingDialog() {
amplitudeUtils.logEvent("view_goalsetting_popup")

val dialog = WineyDialogFragment(
stringOf(R.string.wineyfeed_goal_dialog_title),
stringOf(R.string.wineyfeed_goal_dialog_subtitle),
stringOf(R.string.wineyfeed_goal_dialog_negative_button),
stringOf(R.string.wineyfeed_goal_dialog_positive_button),
handleNegativeButton = {
sendDialogClickEvent(false)
},
handlePositiveButton = {
sendDialogClickEvent(true)
navigateTo<MyPageFragment>()
}
)
dialog.show(parentFragmentManager, TAG_GOAL_DIALOG)
}

private fun sendDialogClickEvent(isNavigate: Boolean) {
val eventProperties = JSONObject()

try {
if (isNavigate) {
eventProperties.put("method", "yes")
} else {
eventProperties.put("method", "no")
}
} catch (e: JSONException) {
System.err.println("Invalid JSON")
e.printStackTrace()
}

amplitudeUtils.logEvent("click_goalsetting", eventProperties)
}

private inline fun <reified T : Fragment> navigateTo() {
parentFragmentManager.commit {
replace<T>(R.id.fcv_main, T::class.simpleName)
Expand Down Expand Up @@ -342,6 +388,35 @@ class WineyFeedFragment :
startActivity(intent)
}

private fun sendWineyFeedEvent(type: EventType, feed: WineyFeed) {
val eventProperties = JSONObject()

try {
eventProperties.put("article_id", feed.feedId)
.put("like_count", feed.likes)
.put("comment_count", feed.comments)

if (type == TYPE_CLICK_LIKE) {
eventProperties.put("from", "feed")
}
} catch (e: JSONException) {
System.err.println("Invalid JSON")
e.printStackTrace()
}

when (type) {
TYPE_CLICK_FEED_ITEM -> amplitudeUtils.logEvent(
"click_homefeed_contents",
eventProperties
)

TYPE_CLICK_LIKE ->
amplitudeUtils.logEvent("click_like", eventProperties)

else -> {}
}
}

companion object {
private const val MSG_WINEYFEED_ERROR = "ERROR"
private const val TAG_GOAL_DIALOG = "NO_GOAL_DIALOG"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import com.android.go.sopt.winey.domain.entity.DetailFeed
import com.android.go.sopt.winey.domain.repository.DataStoreRepository
import com.android.go.sopt.winey.presentation.main.MainActivity
import com.android.go.sopt.winey.util.activity.hideKeyboard
import com.android.go.sopt.winey.util.amplitude.AmplitudeUtils
import com.android.go.sopt.winey.util.amplitude.type.EventType
import com.android.go.sopt.winey.util.binding.BindingActivity
import com.android.go.sopt.winey.util.context.colorOf
import com.android.go.sopt.winey.util.context.snackBar
Expand All @@ -31,6 +33,8 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.json.JSONException
import org.json.JSONObject
import timber.log.Timber
import javax.inject.Inject

Expand All @@ -52,25 +56,28 @@ class DetailActivity : BindingActivity<ActivityDetailBinding>(R.layout.activity_
@Inject
lateinit var dataStoreRepository: DataStoreRepository

@Inject
lateinit var amplitudeUtils: AmplitudeUtils

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.vm = viewModel
removeRecyclerviewItemChangeAnimation()
initBackButtonClickListener()

binding.vm = viewModel
viewModel.getFeedDetail(feedId)

initGetFeedDetailObserver()
initPostLikeStateObserver()
initDeleteFeedStateObserver()

initCommentAdapter()
initCommentCreateButtonClickListener()
initPostCommentStateObserver()
initDeleteCommentStateObserver()

initCommentAdapter()
initCommentCreateButtonClickListener()
initEditTextFocusChangeListener()
updateStatusBarColor()
binding.tvCommentCreate.bringToFront()

removeRecyclerviewItemChangeAnimation()
initBackButtonClickListener()
}

private fun updateStatusBarColor() {
Expand Down Expand Up @@ -272,6 +279,8 @@ class DetailActivity : BindingActivity<ActivityDetailBinding>(R.layout.activity_

val commentList = detailFeed.commentList
switchCommentContainer(commentList)

sendEventToAmplitude(EventType.TYPE_VIEW_SCREEN, detailFeed)
}

is UiState.Failure -> {
Expand Down Expand Up @@ -299,7 +308,8 @@ class DetailActivity : BindingActivity<ActivityDetailBinding>(R.layout.activity_
is UiState.Success -> {
val isLiked = state.data.data.isLiked
val likes = state.data.data.likes.toLong()
detailFeedAdapter.updateLikeNumber(isLiked, likes)
val feed = detailFeedAdapter.updateLikeNumber(isLiked, likes)
sendEventToAmplitude(EventType.TYPE_CLICK_LIKE, feed)
}

is UiState.Failure -> {
Expand Down Expand Up @@ -415,6 +425,33 @@ class DetailActivity : BindingActivity<ActivityDetailBinding>(R.layout.activity_
showAsDropDown(anchorView, -POPUP_MENU_POS_OFFSET, -POPUP_MENU_POS_OFFSET, Gravity.END)
}

private fun sendEventToAmplitude(type: EventType, feed: DetailFeed) {
val eventProperties = JSONObject()

try {
eventProperties.put("article_id", feed.feedId)
.put("like_count", feed.likes)
.put("comment_count", feed.comments)

if (type == EventType.TYPE_CLICK_LIKE) {
eventProperties.put("from", "article")
}
} catch (e: JSONException) {
System.err.println("Invalid JSON")
e.printStackTrace()
}

when (type) {
EventType.TYPE_VIEW_SCREEN -> amplitudeUtils.logEvent(
"view_detail_contents",
eventProperties
)

EventType.TYPE_CLICK_LIKE -> amplitudeUtils.logEvent("click_like", eventProperties)
else -> {}
}
}

companion object {
private const val KEY_FEED_ID = "feedId"
private const val KEY_FEED_WRITER_ID = "feedWriterId"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ class DetailFeedAdapter(
holder.bind(detailFeed)
}

fun updateLikeNumber(isLiked: Boolean, likes: Long) {
fun updateLikeNumber(isLiked: Boolean, likes: Long): DetailFeed {
detailFeed.isLiked = isLiked // 이미지 변경
detailFeed.likes = likes // 개수 변경
notifyItemChanged(0)
return detailFeed
}

fun updateCommentNumber(comments: Long) {
Expand Down
Loading