モバイルから収集する
モバイルプラットフォーム上で、Flipで分析するために必要なデータを収集する方法を紹介します。
1. 関数を定義する
初めに、後のステップで利用する関数を定義します。これらの関数はHTTP APIをベースに作成されています。
- 下のコードを、適当なファイルにコピー&ペーストして下さい。
現時点では、匿名ユーザーのID(
anonymousId
)を作成・格納するロジックは実装されていません。実装方法が分かる方がいましたら、[email protected]までご連絡ください。
import Foundation
class Flip {
let INGESTION_KEY = "プロジェクトの収集キー" // プロジェクトの設定画面に表示されている値に変更して下さい
let TRACK_ENDPOINT = "https://app.flip.inc/v1/track"
let IDENTIFY_ENDPOINT = "https://app.flip.inc/v1/identify"
static let shared = Flip()
private init() {}
func track(name: String,
userId: String? = nil,
anonymousId: String? = nil,
properties: [String: Any]? = nil,
userProperties: [String: Any]? = nil) {
var updatedUserProperties = userProperties ?? [:]
updatedUserProperties["platform"] = "ios"
post(endpoint: TRACK_ENDPOINT, requestBody: [
"name": name,
"originalUserId": userId ?? NSNull(),
"anonymousId": anonymousId ?? NSNull(),
"properties": properties ?? NSNull(),
"userProperties": updatedUserProperties
])
}
func identify(userId: String? = nil,
anonymousId: String? = nil,
properties: [String: Any]? = nil) {
var updatedProperties = properties ?? [:]
updatedProperties["platform"] = "ios"
post(endpoint: IDENTIFY_ENDPOINT, requestBody: [
"originalUserId": userId ?? NSNull(),
"anonymousId": anonymousId ?? NSNull(),
"properties": updatedProperties
])
}
private func post(endpoint: String, requestBody: [String: Any]) {
guard let url = URL(string: endpoint) else {
print("[Flip] Invalid URL")
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
var updatedRequestBody = requestBody
updatedRequestBody["ingestionKey"] = INGESTION_KEY
do {
request.httpBody = try JSONSerialization.data(withJSONObject: updatedRequestBody, options: [])
} catch {
print("[Flip] \(error)")
return
}
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if let error = error {
print("[Flip] \(error)")
return
}
if let httpResponse = response as? HTTPURLResponse, !(200...299).contains(httpResponse.statusCode), let data = data {
do {
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let message = json["message"] as? String {
print("[Flip] \(httpResponse.statusCode) \(message)")
}
} catch {
print("[Flip] \(error)")
}
}
}
task.resume()
}
}
import java.net.HttpURLConnection
import java.net.URL
import org.json.JSONObject
class Flip private constructor() {
companion object {
private const val INGESTION_KEY = "プロジェクトの収集キー" // プロジェクトの設定画面に表示されている値に変更して下さい
private const val TRACK_ENDPOINT = "https://app.flip.inc/v1/track"
private const val IDENTIFY_ENDPOINT = "https://app.flip.inc/v1/identify"
val shared = Flip()
}
fun track(
name: String,
userId: String? = null,
anonymousId: String? = null,
properties: Map<String, Any>? = null,
userProperties: Map<String, Any>? = null
) {
val body = mutableMapOf(
"name" to name,
"originalUserId" to userId,
"anonymousId" to anonymousId,
"properties" to properties,
"userProperties" to (userProperties?.plus("platform" to "android") ?: mapOf("platform" to "android"))
)
post("https://app.flip.inc/v1/track", body)
}
fun identify(
userId: String? = null,
anonymousId: String? = null,
properties: Map<String, Any>? = null
) {
val body = mutableMapOf(
"originalUserId" to userId,
"anonymousId" to anonymousId,
"properties" to (properties?.plus("platform" to "android") ?: mapOf("platform" to "android"))
)
post("https://app.flip.inc/v1/identify", body)
}
private fun post(endpoint: String, requestBody: Map<String, Any>) {
val url = URL(endpoint)
val connection = url.openConnection() as HttpURLConnection
try {
connection.requestMethod = "POST"
connection.setRequestProperty("Content-Type", "application/json")
connection.doOutput = true
val body = JSONObject(requestBody.plus("ingestionKey" to INGESTION_KEY))
connection.outputStream.write(body.toString().toByteArray(Charsets.UTF_8))
val responseCode = connection.responseCode
if (responseCode !in 200..299) {
val response = connection.inputStream.bufferedReader().use { it.readText() }
val jsonResponse = JSONObject(response)
val message = jsonResponse.optString("message")
println("[Flip] $responseCode $message")
}
} catch (e: Exception) {
println("[Flip] $e")
} finally {
connection.disconnect()
}
}
}
import "dart:convert";
import "dart:io";
class Flip {
final String INGESTION_KEY = "プロジェクトの収集キー"; // プロジェクトの設定画面に表示されている値に変更して下さい
final String TRACK_ENDPOINT = "https://app.flip.inc/v1/track";
final String IDENTIFY_ENDPOINT = "https://app.flip.inc/v1/identify";
static final Flip _singleton = Flip._internal();
factory Flip() {
return _singleton;
}
Flip._internal();
void track(
String name,
String? userId,
String? anonymousId,
Map<String, dynamic>? properties,
Map<String, dynamic>? userProperties
) {
_post(TRACK_ENDPOINT, {
"name": name,
"originalUserId": userId,
"anonymousId": anonymousId,
"properties": properties,
"userProperties": {
...?userProperties,
"platform": "flutter",
},
});
}
void identify(
String? userId,
String? anonymousId,
Map<String, dynamic>? properties
) {
_post(IDENTIFY_ENDPOINT, {
"originalUserId": userId,
"anonymousId": anonymousId,
"properties": {
...?properties,
"platform": "flutter",
},
});
}
Future<void> _post(
String endpoint,
Map<String, dynamic> requestBody
) async {
var url = Uri.parse(endpoint);
var client = HttpClient();
try {
var request = await client.postUrl(url);
request.headers.contentType = ContentType.json;
request.write(json.encode({
...requestBody,
"ingestionKey": INGESTION_KEY,
}));
var response = await request.close();
if (response.statusCode != 200) {
var responseBody = await response.transform(utf8.decoder).join();
var jsonResponse = json.decode(responseBody);
var message = jsonResponse["message"];
print("[Flip] ${response.statusCode} $message");
}
} catch (e) {
print("[Flip] $e");
} finally {
client.close();
}
}
}
2. イベントを収集する
イベントを収集することで、ユーザーの一つ一つの操作を記録できるようになります。各引数の具体的な役割に関しては、HTTP APIを参考にして下さい。
- ユーザーが特定の操作を実行した直後(例. 機能を利用)に、次のコードが呼ばれるようにペーストして下さい。コードの内容は自由に変更して構いません。
Flip.shared.track(
name: "message_sent",
userId: "usr_GXfryD0JQivyGa97TgGsT",
anonymousId: nil,
properties: [
"message_type": "画像付きテキスト",
"character_count": 32
],
userProperties: [
"email": "[email protected]",
"name": "Tanaka Masaki",
"position": "プロダクトマネージャー"
]
)
Flip.shared.track(
name = "message_sent",
userId = "usr_GXfryD0JQivyGa97TgGsT",
anonymousId = null,
properties = mapOf(
"message_type" to "画像付きテキスト",
"character_count" to 32
),
userProperties = mapOf(
"email" to "[email protected]",
"name" to "Tanaka Masaki",
"position" to "プロダクトマネージャー"
)
)
Flip().track(
"message_sent",
"usr_GXfryD0JQivyGa97TgGsT",
null,
{
"message_type": "画像付きテキスト",
"character_count": 32
},
{
"email": "[email protected]",
"name": "Tanaka Masaki",
"position": "プロダクトマネージャー"
},
);
3. ユーザー情報を更新する
下のコードを追加することで、イベントを収集することなく、特定のユーザーの情報を更新できます。各引数の具体的な役割に関しては、HTTP APIを参考にして下さい。
- ユーザーの情報が変更された直後(例. 新規登録・オンボーディング)に、次のコードが呼ばれるように下のコードをペーストして下さい。コードの内容は自由に変更して構いません。
Flip.shared.identify(
userId: "usr_GXfryD0JQivyGa97TgGsT",
anonymousId: nil,
properties: [
"email": "[email protected]",
"name": "Tanaka Masaki",
"position": "プロダクトマネージャー"
]
)
Flip.shared.identify(
userId = "usr_GXfryD0JQivyGa97TgGsT",
anonymousId = null,
properties = mapOf(
"email" to "[email protected]",
"name" to "Tanaka Masaki",
"position" to "プロダクトマネージャー"
)
)
Flip().identify(
"usr_GXfryD0JQivyGa97TgGsT",
null,
{
"email": "[email protected]",
"name": "Tanaka Masaki",
"position": "プロダクトマネージャー"
},
);
Updated about 1 month ago