ゲームエンジンから収集する
ゲームエンジン上で、Flipで分析するために必要なデータを収集する方法を紹介します。
1. 関数を定義する
初めに、後のステップで利用する関数を定義します。これらの関数はHTTP APIをベースに作成されています。
- 下のコードを、適当なファイルにコピー&ペーストして下さい。
現時点では、匿名ユーザーのID(
anonymousId
)を作成・格納するロジックは実装されていません。実装方法が分かる方がいましたら、[email protected]までご連絡ください。
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System.Collections.Generic;
using System.Text;
public class Flip : MonoBehaviour
{
private const string INGESTION_KEY = "プロジェクトの収集キー"; // プロジェクトの設定画面に表示されている値に変更して下さい
private const string TRACK_ENDPOINT = "https://app.flip.inc/v1/track";
private const string IDENTIFY_ENDPOINT = "https://app.flip.inc/v1/identify";
public void Track(string name, string userId = null, string anonymousId = null,
Dictionary<string, object> properties = null, Dictionary<string, object> userProperties = null)
{
if (userProperties == null)
userProperties = new Dictionary<string, object>();
userProperties["platform"] = "unity";
var requestBody = new Dictionary<string, object>
{
{"name", name},
{"originalUserId", userId},
{"anonymousId", anonymousId},
{"properties", properties},
{"userProperties", userProperties},
};
StartCoroutine(Post(TRACK_ENDPOINT, requestBody));
}
public void Identify(string userId = null, string anonymousId = null,
Dictionary<string, object> properties = null)
{
if (properties == null)
properties = new Dictionary<string, object>();
properties["platform"] = "unity";
var requestBody = new Dictionary<string, object>
{
{"originalUserId", userId},
{"anonymousId", anonymousId},
{"properties", properties},
};
StartCoroutine(Post(IDENTIFY_ENDPOINT, requestBody));
}
private IEnumerator Post(string endpoint, Dictionary<string, object> requestBody)
{
requestBody["ingestionKey"] = INGESTION_KEY;
var requestBodyJson = JsonUtility.ToJson(requestBody);
var request = new UnityWebRequest(endpoint, "POST");
request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(requestBodyJson));
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
{
Debug.LogError($"[Flip] {request.error}");
}
else if (!string.IsNullOrEmpty(request.downloadHandler.text))
{
var response = JsonUtility.FromJson<Response>(request.downloadHandler.text);
if (request.responseCode != 200)
{
Debug.LogError($"[Flip] {request.responseCode} {response.message}");
}
}
}
[System.Serializable]
private class Response
{
public string message;
}
}
////////////////////////
// Flip.hに書く内容
////////////////////////
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "JsonUtilities.h"
#include "Flip.generated.h"
UCLASS()
class YOUR_PROJECT_NAME_API UFlip : public UObject // YOUR_PROJECT_NAMEは実際のプロジェクト名に変更して下さい
{
GENERATED_BODY()
public:
void Track(FString name,
FString userId = TEXT(""),
FString anonymousId = TEXT(""),
TSharedPtr<FJsonObject> properties = nullptr,
TSharedPtr<FJsonObject> userProperties = nullptr);
void Identify(FString userId = TEXT(""),
FString anonymousId = TEXT(""),
TSharedPtr<FJsonObject> properties = nullptr);
private:
static const FString INGESTION_KEY;
static const FString TRACK_ENDPOINT;
static const FString IDENTIFY_ENDPOINT;
void Post(FString endpoint, TSharedPtr<FJsonObject> requestBody);
void OnResponseReceived(FHttpRequestPtr request, FHttpResponsePtr response, bool bWasSuccessful);
};
////////////////////////
// Flip.cppに書く内容
////////////////////////
#include "Flip.h"
#include "Runtime/Online/HTTP/Public/Http.h"
#include "JsonUtilities.h"
const FString UFlip::INGESTION_KEY = TEXT("プロジェクトの収集キー"); // プロジェクトの設定画面に表示されている値に変更して下さい
const FString UFlip::TRACK_ENDPOINT = TEXT("https://app.flip.inc/v1/track");
const FString UFlip::IDENTIFY_ENDPOINT = TEXT("https://app.flip.inc/v1/identify");
void UFlip::Track(FString name, FString userId, FString anonymousId, TSharedPtr<FJsonObject> properties, TSharedPtr<FJsonObject> userProperties)
{
TSharedPtr<FJsonObject> body = MakeShareable(new FJsonObject());
body->SetStringField(TEXT("name"), name);
if (!userId.IsEmpty()) body->SetStringField(TEXT("originalUserId"), userId);
if (!anonymousId.IsEmpty()) body->SetStringField(TEXT("anonymousId"), anonymousId);
if (properties.IsValid()) body->SetObjectField(TEXT("properties"), properties);
if (!userProperties.IsValid())
{
userProperties = MakeShareable(new FJsonObject());
}
userProperties->SetStringField(TEXT("platform"), TEXT("unreal"));
body->SetObjectField(TEXT("userProperties"), userProperties);
Post(TRACK_ENDPOINT, body);
}
void UFlip::Identify(FString userId, FString anonymousId, TSharedPtr<FJsonObject> properties)
{
TSharedPtr<FJsonObject> body = MakeShareable(new FJsonObject());
if (!userId.IsEmpty()) body->SetStringField(TEXT("originalUserId"), userId);
if (!anonymousId.IsEmpty()) body->SetStringField(TEXT("anonymousId"), anonymousId);
if (!properties.IsValid())
{
properties = MakeShareable(new FJsonObject());
}
properties->SetStringField(TEXT("platform"), TEXT("unreal"));
body->SetObjectField(TEXT("properties"), properties);
Post(IDENTIFY_ENDPOINT, body);
}
void UFlip::Post(FString endpoint, TSharedPtr<FJsonObject> requestBody)
{
requestBody->SetStringField(TEXT("ingestionKey"), INGESTION_KEY);
FString contentString;
TSharedRef<TJsonWriter<>> writer = TJsonWriterFactory<>::Create(&contentString);
FJsonSerializer::Serialize(requestBody.ToSharedRef(), writer);
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> request = FHttpModule::Get().CreateRequest();
request->SetVerb("POST");
request->SetURL(endpoint);
request->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
request->SetContentAsString(contentString);
request->OnProcessRequestComplete().BindUObject(this, &UFlip::OnResponseReceived);
request->ProcessRequest();
}
void UFlip::OnResponseReceived(FHttpRequestPtr request, FHttpResponsePtr response, bool bWasSuccessful)
{
if (!bWasSuccessful || !response.IsValid())
{
UE_LOG(LogTemp, Error, TEXT("[Flip] Failed to get a valid response"));
return;
}
if (!EHttpResponseCodes::IsOk(response->GetResponseCode()))
{
TSharedPtr<FJsonObject> body;
TSharedRef<TJsonReader<>> reader = TJsonReaderFactory<>::Create(response->GetContentAsString());
if (FJsonSerializer::Deserialize(reader, body) && body.IsValid())
{
FString message = body->GetStringField("message");
UE_LOG(LogTemp, Error, TEXT("[Flip] %d %s"), response->GetResponseCode(), *message);
}
}
}
2. イベントを収集する
イベントを収集することで、ユーザーの一つ一つの操作を記録できるようになります。各引数の具体的な役割に関しては、HTTP APIを参考にして下さい。
- ユーザーが特定の操作を実行した直後(例. 機能を利用)に、次のコードが呼ばれるようにペーストして下さい。コードの内容は自由に変更して構いません。
Flip flip = GetComponent<Flip>();
Dictionary<string, object> properties = new Dictionary<string, object>
{
{"message_type", "画像付きテキスト"},
{"character_count", 32}
};
Dictionary<string, object> userProperties = new Dictionary<string, object>
{
{"email", "[email protected]"},
{"name", "Tanaka Masaki"},
{"position", "プロダクトマネージャー"}
};
flip.Track(
name: "message_sent",
userId: "usr_GXfryD0JQivyGa97TgGsT",
properties: properties,
userProperties: userProperties
);
TSharedPtr<FJsonObject> properties = MakeShareable(new FJsonObject());
properties->SetStringField(TEXT("message_type"), TEXT("画像付きテキスト"));
properties->SetNumberField(TEXT("character_count"), 32);
TSharedPtr<FJsonObject> userProperties = MakeShareable(new FJsonObject());
userProperties->SetStringField(TEXT("email"), TEXT("[email protected]"));
userProperties->SetStringField(TEXT("name"), TEXT("Tanaka Masaki"));
userProperties->SetStringField(TEXT("position"), TEXT("プロダクトマネージャー"));
UFlip* Flip = NewObject<UFlip>();
Flip->Track(TEXT("message_sent"), TEXT("usr_GXfryD0JQivyGa97TgGsT"), TEXT(""), properties, userProperties);
3. ユーザー情報を更新する
下のコードを追加することで、イベントを収集することなく、特定のユーザーの情報を更新できます。各引数の具体的な役割に関しては、HTTP APIを参考にして下さい。
- ユーザーの情報が変更された直後(例. 新規登録・オンボーディング)に、次のコードが呼ばれるように下のコードをペーストして下さい。コードの内容は自由に変更して構いません。
Flip flip = GetComponent<Flip>();
Dictionary<string, object> properties = new Dictionary<string, object>
{
{"email", "[email protected]"},
{"name", "Tanaka Masaki"},
{"position", "プロダクトマネージャー"}
};
flip.Identify(
userId: "usr_GXfryD0JQivyGa97TgGsT",
properties: properties
);
TSharedPtr<FJsonObject> properties = MakeShareable(new FJsonObject());
properties->SetStringField(TEXT("email"), TEXT("[email protected]"));
properties->SetStringField(TEXT("name"), TEXT("Tanaka Masaki"));
properties->SetStringField(TEXT("position"), TEXT("プロダクトマネージャー"));
UFlip* Flip = NewObject<UFlip>();
Flip->Identify(TEXT("usr_GXfryD0JQivyGa97TgGsT"), TEXT(""), properties);
Updated about 1 month ago