앱스플라이어 딥링크 설정

- 앱스플라이어 Onelink를 타고 들어온 경우 pid와 utm설정
This commit is contained in:
Yu Sung 2025-03-06 18:58:07 +09:00
parent cc318e809f
commit 285eb585e0
8 changed files with 94 additions and 36 deletions

View File

@ -124,22 +124,28 @@ extension AppDelegate: DeepLinkDelegate {
return
}
UserDefaults.set(deepLinkObj.clickEvent["deep_link_sub1"] as? String ?? "", forKey: .marketingPid)
let pid = deepLinkObj.clickEvent["deep_link_sub1"] as? String ?? ""
if !pid.isEmpty {
UserDefaults.set(pid, forKey: .marketingPid)
}
AppState.shared.marketingUtmSource = deepLinkObj.clickEvent["deep_link_sub2"] as? String ?? ""
AppState.shared.marketingUtmMedium = deepLinkObj.clickEvent["deep_link_sub3"] as? String ?? ""
AppState.shared.marketingUtmCampaign = deepLinkObj.clickEvent["deep_link_sub4"] as? String ?? ""
let deepLinkValue = deepLinkObj.clickEvent["deep_link_value"] as? String ?? ""
let deepLinkValueId = Int(deepLinkObj.clickEvent["deep_link_sub5"] as? String ?? "") ?? 0
if deepLinkValue == "series" {
AppState.shared.pushSeriesId = deepLinkObj.clickEvent["deep_link_sub5"] as? Int ?? 0
} else if deepLinkValue == "content" {
AppState.shared.pushAudioContentId = deepLinkObj.clickEvent["deep_link_sub5"] as? Int ?? 0
} else if deepLinkValue == "live" {
AppState.shared.pushRoomId = deepLinkObj.clickEvent["deep_link_sub5"] as? Int ?? 0
} else if deepLinkValue == "channel" {
AppState.shared.pushChannelId = deepLinkObj.clickEvent["deep_link_sub5"] as? Int ?? 0
if deepLinkValueId > 0 {
if deepLinkValue == "series" {
AppState.shared.pushSeriesId = deepLinkValueId
} else if deepLinkValue == "content" {
AppState.shared.pushAudioContentId = deepLinkValueId
} else if deepLinkValue == "live" {
AppState.shared.pushRoomId = deepLinkValueId
} else if deepLinkValue == "channel" {
AppState.shared.pushChannelId = deepLinkValueId
}
}
logUtmInFirebase()

View File

@ -0,0 +1,50 @@
//
// AppViewModel.swift
// SodaLive
//
// Created by klaus on 3/6/25.
//
import Combine
import AdSupport
import AppTrackingTransparency
final class AppViewModel: ObservableObject {
private var subscription = Set<AnyCancellable>()
private let userRepository = UserRepository()
func fetchAndUpdateIdfa() {
DEBUG_LOG("fetchAndUpdateIdfa")
ATTrackingManager.requestTrackingAuthorization { [unowned self] status in
if status == .authorized {
let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
let pid = UserDefaults.string(forKey: .marketingPid)
self.userRepository.updateMarketingInfo(request: MarketingInfoUpdateRequest(adid: idfa, pid: pid))
.sink { result in
switch result {
case .finished:
DEBUG_LOG("finish")
case .failure(let error):
ERROR_LOG(error.localizedDescription)
}
} receiveValue: { _ in
}
.store(in: &self.subscription)
} else {
let pid = UserDefaults.string(forKey: .marketingPid)
self.userRepository.updateMarketingInfo(request: MarketingInfoUpdateRequest(adid: "", pid: pid))
.sink { result in
switch result {
case .finished:
DEBUG_LOG("finish")
case .failure(let error):
ERROR_LOG(error.localizedDescription)
}
} receiveValue: { _ in
}
.store(in: &self.subscription)
}
}
}
}

View File

@ -6,7 +6,6 @@
//
import SwiftUI
import AppTrackingTransparency
import FBSDKCoreKit
import AppsFlyerLib
@ -16,6 +15,8 @@ struct SodaLiveApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@ObservedObject var viewModel = AppViewModel()
var body: some Scene {
WindowGroup {
ContentView()
@ -26,7 +27,7 @@ struct SodaLiveApp: App {
UIApplication.shared.applicationIconBadgeNumber = 0
AppsFlyerLib.shared().start()
ATTrackingManager.requestTrackingAuthorization { _ in }
viewModel.fetchAndUpdateIdfa()
}
.onOpenURL { url in
DEBUG_LOG("I have received a URL through a custom scheme! \(url.absoluteString)")

View File

@ -174,7 +174,6 @@ struct HomeView: View {
}
.onAppear {
pushTokenUpdate()
viewModel.fetchAndUpdateIdfa()
viewModel.getMemberInfo()
viewModel.getEventPopup()
viewModel.addAllPlaybackTracking()

View File

@ -8,9 +8,6 @@
import Foundation
import Combine
import AppTrackingTransparency
import AdSupport
final class HomeViewModel: ObservableObject {
private var subscription = Set<AnyCancellable>()
@ -53,25 +50,6 @@ final class HomeViewModel: ObservableObject {
.store(in: &subscription)
}
func fetchAndUpdateIdfa() {
ATTrackingManager.requestTrackingAuthorization { [unowned self] status in
if status == .authorized {
let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
self.userRepository.updateIdfa(request: IdfaUpdateRequest(adid: idfa))
.sink { result in
switch result {
case .finished:
DEBUG_LOG("finish")
case .failure(let error):
ERROR_LOG(error.localizedDescription)
}
} receiveValue: { _ in
}
.store(in: &self.subscription)
}
}
}
func getMemberInfo() {
userRepository.getMemberInfo()
.sink { result in

View File

@ -0,0 +1,13 @@
//
// MarketingInfoUpdateRequest.swift
// SodaLive
//
// Created by klaus on 3/6/25.
//
import Foundation
struct MarketingInfoUpdateRequest: Encodable {
let adid: String
let pid: String
}

View File

@ -33,6 +33,7 @@ enum UserApi {
case checkNickname(nickname: String)
case changeNickname(request: ProfileUpdateRequest)
case updateIdfa(request: IdfaUpdateRequest)
case updateMarketingInfo(request: MarketingInfoUpdateRequest)
case getMemberProfile(memberId: Int)
}
@ -109,6 +110,9 @@ extension UserApi: TargetType {
case .updateIdfa:
return "/member/adid/update"
case .updateMarketingInfo:
return "/member/marketing-info/update"
case .getMemberProfile(let memberId):
return "/member/profile/\(memberId)"
}
@ -123,7 +127,7 @@ extension UserApi: TargetType {
case .searchUser, .getMypage, .getMemberInfo, .getMyProfile, .getChangeNicknamePrice, .checkNickname, .getBlockedMemberList, .getBlockedMemberIdList, .getMemberProfile:
return .get
case .updatePushToken, .profileUpdate, .changeNickname, .updateIdfa:
case .updatePushToken, .profileUpdate, .changeNickname, .updateIdfa, .updateMarketingInfo:
return .put
}
}
@ -187,6 +191,9 @@ extension UserApi: TargetType {
case .updateIdfa(let request):
return .requestJSONEncodable(request)
case .updateMarketingInfo(let request):
return .requestJSONEncodable(request)
}
}

View File

@ -122,6 +122,10 @@ final class UserRepository {
return api.requestPublisher(.updateIdfa(request: request))
}
func updateMarketingInfo(request: MarketingInfoUpdateRequest) -> AnyPublisher<Response, MoyaError> {
return api.requestPublisher(.updateMarketingInfo(request: request))
}
func getMemberProfile(memberId: Int) -> AnyPublisher<Response, MoyaError> {
return api.requestPublisher(.getMemberProfile(memberId: memberId))
}