顯示具有 uuid 標籤的文章。 顯示所有文章
顯示具有 uuid 標籤的文章。 顯示所有文章

2019年9月18日 星期三

iOS 開發筆記 - 使用 Swift 完成 GA Measurement Protocol 實作

大概去年夏天,偶爾會寫一點 Swift 程式,雖然對 Objective c 比較熟,但時勢變遷就該順應潮流。那時採用 GoogleAnalytics 套件,但 Google Analytics for App 要在今年秋天下線了,Google一直要大家改用 Firebase ,且 Google 牌 cocoapods GoogleAnalytics 也的確幾年沒更新了。只是 Firebase 就明顯要人多花錢,例如要先把 Firebase 的數據匯入到 GA 上免錢,但有些查詢又要搞到 BigQuery 才行,雖然 BigQuery 有免費額度 啦 XD 因此趁 GA Measurement Protocol 還沒下線前,多用用他吧!把以前是 App Screen 就設法轉成 Web Pageview 吧,唯一的缺點是 Session 這類,若要硬做也是一招啦,在此就都不管了。

在此只包裝成 3 個函式供人使用即可,分別是取得 clientID、回報 pageview、回報 event 既可:

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.

GAEvent(trackingID: "UA-########-#", clientID: getClientID(), eventCategory: "TestEC", eventAction: "TestEA", eventLabel: "TestEL", eventValue: 0)

GAPageView(trackingID: "UA-########-#", clientID: getClientID(), path:"/")
}

func getClientID() -> String {
// example
return UUID().uuidString
}

func GAPageView(trackingID:String, clientID:String, path:String ) {
var url = URLComponents(string: "https://www.google-analytics.com/collect")!
if trackingID.isEmpty || clientID.isEmpty || path.isEmpty {
return
}
url.queryItems = [
URLQueryItem(name: "v", value: "1"),
URLQueryItem(name: "tid", value: trackingID),
URLQueryItem(name: "cid", value: clientID),
URLQueryItem(name: "t", value: "pageview"),
URLQueryItem(name: "dh", value: "example.com"),
URLQueryItem(name: "dp", value: path),
]
//#if DEBUG
//url.queryItems?.append(URLQueryItem(name: "cd1", value: "DEBUG"))
//#endif
//if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String, appVersion.isEmpty {
//    url.queryItems?.append(URLQueryItem(name: "cd2", value: appVersion))
//}

let request = URLRequest(url: url.url!)
let task = URLSession.shared.dataTask(with: request) {(data, response, error) in
//guard let data = data else { return }
//print(String(data: data, encoding: .utf8)!)
if let httpResponse = response as? HTTPURLResponse {
print("GAPageView: \(httpResponse.statusCode)" )
}
}
task.resume()
}

func GAEvent(trackingID:String, clientID:String, eventCategory:String, eventAction:String, eventLabel:String, eventValue:Int) {
var url = URLComponents(string: "https://www.google-analytics.com/collect")!
if trackingID.isEmpty || clientID.isEmpty || path.isEmpty {
return
}

url.queryItems = [
URLQueryItem(name: "v", value: "1"),
URLQueryItem(name: "tid", value: trackingID),
URLQueryItem(name: "cid", value: clientID),
URLQueryItem(name: "t", value: "event"),
URLQueryItem(name: "ec", value: eventCategory),
]
//#if DEBUG
//url.queryItems?.append(URLQueryItem(name: "cd1", value: "DEBUG"))
//#endif
//if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String, appVersion.isEmpty {
//    url.queryItems?.append(URLQueryItem(name: "cd2", value: appVersion))
//}

if !eventAction.isEmpty {
url.queryItems?.append(URLQueryItem(name: "ea", value: eventAction))
if !eventLabel.isEmpty {
url.queryItems?.append(URLQueryItem(name: "el", value: eventAction))
if eventValue >= 0 {
url.queryItems?.append(URLQueryItem(name: "ev", value: "\(eventValue)"))
}
}
}

let request = URLRequest(url: url.url!)
let task = URLSession.shared.dataTask(with: request) {(data, response, error) in
//guard let data = data else { return }
//print(String(data: data, encoding: .utf8)!)
if let httpResponse = response as? HTTPURLResponse {
print("GAEvent: \(httpResponse.statusCode)" )
}
}
task.resume()
}


其中 getClientID() 只是個示意,因為每次呼叫 UUID().uuidString 都會產生一組新的,可以把它存起來使用,或是針對某些情境設計規劃,像是服務有提供登入機制時,就改用從 user id 計算得出等那類即可。

2014年4月12日 星期六

iOS 開發筆記 - Improper Advertising identifier [IDFA] Usage. Your app contains the Advertising Identifier [IDFA] API but you have not indicated its usage on the prepare for Upload page in iTunes Connect.



在 2014-04-10 上傳 ipa 發現這這問題:
Improper Advertising identifier [IDFA] Usage. Your app contains the Advertising Identifier [IDFA] API but you have not indicated its usage on the prepare for Upload page in iTunes Connect.
解法有兩種:
  • 將程式內有用到 UUID/UDID 的部分去掉(如 Google Analytics Library 等),再重新上傳
  • 設法先退可簽署 IDFA 條約的狀態,重新上傳
其中要退回到簽署 IDFA 的部分,可以做的方式有兩種:
  • 將 app 內有用到跟 UUID/UDID 相關的移掉,進行重新上傳到 iTunes Connect,再把 reject 它,重新填寫跟 IDFA 相關的條款,再重新上傳 iTunes Connect
  • 建立 empty project ,將 Bundle Identifier 設成跟 app 一樣,上傳到 iTunes Connect,再 reject 它,重新填寫跟 IDFA 相關的條款,再重新上傳 iTunes Connect
後來,我選擇不用改 code 的部分,當然也要先把狀態改回到可以簽署 IDFA 流程,就選擇建立 empty project 來處理(此外,可以從原先的 app project 把Images.xcassets複製來用)。只是一樣的程式碼幾個禮拜前沒問題,為何這幾天出事?真是令人不解。

今早 2014-04-12 測試時,一樣的 code 發現又沒 IDFA 問題了 Orz 但還是把碰到這怪現象的解法記錄一下。

註 UDID/UUID 相關:

#import <AdSupport/ASIdentifierManager.h>

if (NSClassFromString(@"ASIdentifierManager")) {
    NSLog(@"ID: %@", [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString]);
} else {
    NSLog(@"ID: %@", [[UIDevice currentDevice] uniqueIdentifier]);
}


Updated @ 2014-05-02 : iOS 開發筆記 - 使用 AdMob 與 IDFA 的處理