menu
Is this helpful?

# 프리셋 App Push 구현 가이드

# Android Push 통합 가이드

# FCM Push

# 1.1 "Push ID"를 전송

  • TE의 로그인 또는 계정 전환 후, FCM의 Token을 업로드해야 합니다.
//TE SDK 초기화
ThinkingAnalyticsSDK instance = ThinkingAnalyticsSDK.sharedInstance(this, APPID, SERVER_URL);
instance.login("user_id");
FirebaseMessaging.getInstance().getToken()
    .addOnCompleteListener(new OnCompleteListener<String>() {
        @Override
        public void onComplete(@NonNull Task<String> task) {
          if (!task.isSuccessful()) {
            Log.w(TAG, "Fetching FCM registration token failed", task.getException());
            return;
          }

          // Get new FCM registration token
          String token = task.getResult();
          JSONObject properties = new JSONObject();
          properties.put("fcm_token",token);
          instance.user_set(properties);
        }
 });
  • FCM Token 변경 시, 유저 속성도 동시 변경:
@Override
public void onNewToken(@NonNull String token) {
    JSONObject properties = new JSONObject();
    properties.put("fcm_token",token);
    instance.user_set(properties);
}

# 1.2 푸시 클릭 이벤트 수집

유저가 알림을 클릭했을 때 푸시 클릭 이벤트를 업로드하고, onCreate 또는 onNewIntent에서 푸시 파라미터를 가져올 수 있습니다.

public class PushOpenClickActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handlePushOpen();
    }
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handlePushOpen();
    }

    private void handlePushOpen() {
        try {
            Intent intent = getIntent();
            if (intent == null) {
                return;
            }
            Bundle bundle = intent.getExtras();
            if (bundle == null) {
                return;
            }
            String teExtras = bundle.getString("te_extras");
            TEPushUtil.trackAppOpenNotification(teExtras);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

# 1.3 칸반 푸시 메시지 처리

  • 일반 파라미터: handleTEPushAction 메소드를 호출합니다.
  • 패스스루 파라미터: handleTEPassThroughAction 메소드를 호출합니다.
public class PushOpenClickActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handlePushOpen();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handlePushOpen();
    }

    private void handlePushOpen() {
        try {
            Intent intent = getIntent();
            if (intent == null) {
                return;
            }
            Bundle bundle = intent.getExtras();
            if (bundle == null) {
                return;
            }
            String teExtras = bundle.getString("te_extras");
            //일반 파라미터
            TEPushUtil.handleTEPushAction(teExtras);
            //PassThrough 파라미터 
            TEPushUtil.handleTEPassThroughAction(teExtras);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

# 부록:

# 클라이언트가 받은 푸시 파라미터의 예

{
    "te_extras": {
        //푸시 클릭의 점프 방법
        "ops_loading_type": "OPEN_APP",
        //패스스루 파라미터
        "passthrough_params": {
                "param1": "abc",
                "param2": 101,
                "param3": [{
                        "subText1": "xyz",
                        "subText2": 2
                }]
        },
        // TE 운영 채널의 수신 속성
        "#ops_receipt_properties": {
                "ops_task_id": "0082",
                "ops_project_id": 1,
                "ops_task_instance_id": "0082_20230331",
                "ops_push_language": "default",
                "ops_task_exec_detail_id": "55"
        }
    }
}

# trackAppOpenNotification

public static void trackAppOpenNotification(String extras) {
    try {
        if (TextUtils.isEmpty(extras)) {
            return;
        }
        JSONObject jsonObject = new JSONObject(extras);
        JSONObject properties = new JSONObject();
        Object obj = json.opt("#ops_receipt_properties");
        JSONObject ops = null;
        if (obj instanceof String) {
            ops = new JSONObject(( String ) obj);
        } else if (obj instanceof JSONObject) {
            ops = ( JSONObject ) obj;
        }
        properties.put("#ops_receipt_properties", ops);
        ThinkingAnalyticsSDK instance = ThinkingAnalyticsSDK.sharedInstance(null, "appId", "serverUrl");
        instance.track("ops_push_click", properties);
    //즉시 전송
        instance.flush();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

# handleTEPushAction

public static void handleTEPushAction(String extras) {
    try {
        if (TextUtils.isEmpty(extras)) {
            return;
        }
        JSONObject jsonObject = new JSONObject(extras);
        String type = jsonObject.optString("ops_loading_type");
        if ("OPEN_APP".equals(type)) {
           // TODO 앱의 메시지를 여는 처리 →앱을 시작해주세요

        } else if ("OPEN_URL".equals(type)) {
            String url = jsonObject.optString("ops_url");
            if (!TextUtils.isEmpty(url)) {
               // TODO URL을 처리하다 →URL 처리를 해주세요
            }
        } else if ("CUSTOMIZED".equals(type)) {
            String custom = jsonObject.optString("ops_customized");
            if (!TextUtils.isEmpty(custom)) {
// TODO 맞춤형 메시지를 처리 → 맞춤형 메시지를 처리해주세요
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

# handleTEPassThroughAction

public static void handleTEPassThroughAction(String extras) {
    try {
        if (TextUtils.isEmpty(extras)) {
            return;
        }
        JSONObject jsonObject = new JSONObject(extras);
        String params = jsonObject.optString("passthrough_params");
//params는 파라미터로, 다음에 구체적인 업무 로직을 실행 계획합니다.
    } catch (Exception e) {
        e.printStackTrace();
    }
}

# TEPushUtil 클래스

public class TEPushUtil {

    public static void trackAppOpenNotification(String extras) {
        try {
            if (TextUtils.isEmpty(extras)) {
                return;
            }
            JSONObject jsonObject = new JSONObject(extras);
            JSONObject properties = new JSONObject();
            Object obj = json.opt("#ops_receipt_properties");
            JSONObject ops = null;
            if (obj instanceof String) {
                ops = new JSONObject(( String ) obj);
            } else if (obj instanceof JSONObject) {
                ops = ( JSONObject ) obj;
            }
            properties.put("#ops_receipt_properties", ops);
            ThinkingAnalyticsSDK instance = ThinkingAnalyticsSDK.sharedInstance(null, "appId", "serverUrl");
            instance.track("ops_push_click", properties);
            //즉시 전송

            instance.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void handleTEPushAction(String extras) {
        try {
            if (TextUtils.isEmpty(extras)) {
                return;
            }
            JSONObject jsonObject = new JSONObject(extras);
            String type = jsonObject.optString("ops_loading_type");
            if ("OPEN_APP".equals(type)) {
            // TODO 앱의 메시지를 여는 처리 → 앱을 시작해주세요
            } else if ("OPEN_URL".equals(type)) {
                String url = jsonObject.optString("ops_url");
                if (!TextUtils.isEmpty(url)) {
            // TODO 업로드 URL을 처리하십시오
                }
            } else if ("CUSTOMIZED".equals(type)) {
                String custom = jsonObject.optString("ops_customized");
                if (!TextUtils.isEmpty(custom)) {
                // TODO 사용자 정의 메시지를 처리하세요

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void handleTEPassThroughAction(String extras) {
        try {
            if (TextUtils.isEmpty(extras)) {
                return;
            }
            JSONObject jsonObject = new JSONObject(extras);
            String params = jsonObject.optString("passthrough_params");
        //params는 파라미터로, 다음에 구체적인 업무 로직을 연결합니다.
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getPushExtras(Object notificationExtras) {
        String teExtras = "";
        try {
            if (notificationExtras != null) {
                if (notificationExtras instanceof String) {
                    teExtras = new JSONObject((String) notificationExtras).optString("te_extras");
                } else if (notificationExtras instanceof Map) {
                    teExtras = new JSONObject((Map) notificationExtras).optString("te_extras");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return teExtras;
    }

}

# iOS Push

# 2.1 "Push ID"를 전송

  • TE의 로그인 또는 계정 전환 후, APNs의 토큰을 업로드해야 합니다.
NSString *appid = @"appid";
NSString *url = @"url";
TDConfig *config = [TDConfig new];
config.appid = appid;
config.configureURL = url;
ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK startWithConfig:config];

[[FIRMessaging messaging] tokenWithCompletion:^(NSString *token, NSError *error) {
      if (error != nil) {
        NSLog(@"Error getting FCM registration token: %@", error);
      } else {
        NSLog(@"FCM registration token: %@", token);
        [instance user_set:@{@"fcm_token": token}];
      }
}];

# 2.2 푸시 클릭 이벤트 수집

// Handle notification messages after display notification is tapped by the user.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void(^)(void))completionHandler {
    NSDictionary *userInfo = response.notification.request.content.userInfo;

   // MyClass는 클릭 이벤트를 전송하는 예제 이름입니다. - trackAppOpenNotification 메소드의 정의는 다음과 같습니다.
    [MyClass trackAppOpenNotification:userInfo];
    
    completionHandler();
}

# 2.3 푸시 메시지 처리

  • 일반 파라미터: handleTEPushAction 메소드를 호출합니다.
  • 패스스루 파라미터: handleTEPassThroughAction 메소드를 호출합니다.
// Handle notification messages after display notification is tapped by the user.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void(^)(void))completionHandler {
    NSDictionary *userInfo = response.notification.request.content.userInfo;
    
//일반 파라미터를 처리할 때, 다음의 메소드를 호출합니다. MyClass는 예시의 이름입니다. handleTEPushAction: 메소드의 정의는 아래에 정의되어 있습니다.
    [MyClass handleTEPushAction:userInfo];
    
//경로 분석 파라미터를 처리할 때, 아래의 메소드를 호출합니다. MyClass는 계산 방법의 예시 이름입니다. handleTEPassThroughAction: 메소드의 정의는 아래에 나타나 있습니다.
    [MyClass handleTEPassThroughAction:userInfo];
    
    completionHandler();
}

# 부록:

# 클라이언트가 받은 푸시 파라미터의 예

{
    "te_extras": {
         //푸시 클릭의 점프 방법

        "ops_loading_type": "OPEN_APP",
        //파라미터 통과

        "passthrough_params": {
                "param1": "abc",
                "param2": 101,
                "param3": [{
                        "subText1": "xyz",
                        "subText2": 2
                }]
        },
        //TE운영 모듈의 수신 속성

        "#ops_receipt_properties": {
                "ops_task_id": "0082",
                "ops_project_id": 1,
                "ops_task_instance_id": "0082_20230331",
                "ops_push_language": "default",
                "ops_task_exec_detail_id": "55"
        }
    }
}

# trackAppOpenNotification

+ (void)trackAppOpenNotification:(NSDictionary *)userInfo{
    NSMutableDictionary *pushProperties = [NSMutableDictionary dictionary]; // track dictionary
    @try {
        NSData *jsonData = [userInfo[@"te_extras"] dataUsingEncoding:NSUTF8StringEncoding];
        NSError *error;
        NSDictionary *sfDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
        if (!error && [sfDictionary isKindOfClass:NSDictionary.class]) {
            pushProperties[@"#ops_receipt_properties"] = sfDictionary[@"#ops_receipt_properties"];
        }
        [[ThinkingAnalyticsSDK sharedInstance]track:@"ops_push_click" properties:pushProperties];
        [[ThinkingAnalyticsSDK sharedInstance]flush];
    } @catch (NSException *exception) {
        
    }
}

# handleTEPushAction

+ (void)handleTEPushAction:(NSDictionary *)userInfo{
    NSMutableDictionary *pushProperties = [NSMutableDictionary dictionary]; // track dictionary
    @try {
        NSString *jsonString = userInfo[@"te_extras"];
        NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
        NSError *error;
        NSDictionary *sfDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
        if (!sfDictionary || error) {
            return;
        }
        NSString *sf_landing_type = sfDictionary[@"ops_loading_type"];
        if ([sf_landing_type isEqualToString:@"OPEN_APP"]) {
        // 오픈 서비스 앱

        }
        else if ([sf_landing_type isEqualToString:@"OPEN_URL"]) {
        // open URL
           NSString *url = sfDictionary[@"ops_url"];
        }
        else if ([sf_landing_type isEqualToString:@"CUSTOMIZED"]) {
        // 사용자 정의 메시지의 처리
           NSString *customized = sfDictionary[@"ops_customized"];
        }
        
    } @catch (NSException *exception) {
        
    }
}

# handleTEPassThroughAction

+ (void)handleTEPassThroughAction:(NSDictionary *)userInfo{
    NSMutableDictionary *pushProperties = [NSMutableDictionary dictionary]; // track dictionary
    @try {
        NSString *jsonString = userInfo[@"te_extras"];
        NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
        NSError *error;
        NSDictionary *sfDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
        if (!sfDictionary || error) {
            return;
        }
        NSString *params = sfDictionary[@"passthrough_params"];
    //params는 파라미터를 패스스루합니다. 다음에 구체적인 업무 로직을 연결합니다.
    } @catch (NSException *exception) {
        
    }
}

# Unity

# 3.1 "Push ID"를 전송

  • TE의 로그인 또는 계정 전환 후, FCM의 토큰을 업로드해야 합니다.
//TE SDK 초기화
ThinkingAnalyticsAPI.StartThinkingAnalytics("APP_ID", "SERVER_URL");
//어카운트ID 설치
ThinkingAnalyticsAPI.Login("ACCOUNT_ID");
//FCM token을 TE에 전송
Firebase.Messaging.FirebaseMessaging.GetTokenAsync().ContinueWith(task => {
    var result = task.Result;
    ThinkingAnalyticsAPI.UserSet(new Dictionary<string, object>() { 
        { "fcm_token", task.Result } 
    });
});
  • FCM Token 변경 시, 유저 속성도 동시 변경:
private void Start()
{
     // FCM 토큰 갱신 가능 이벤트의 등록

    Firebase.Messaging.FirebaseMessaging.TokenReceived += OnTokenReceived;
    Firebase.Messaging.FirebaseMessaging.MessageReceived += OnMessageReceived;
}

public void OnTokenReceived(object sender, Firebase.Messaging.TokenReceivedEventArgs token)
{
    //FCM 토큰을 TE에 전송
    ThinkingAnalyticsAPI.UserSet(new Dictionary<string, object>() { 
        { "fcm_token", token.Token } 
    });
}

# 3.2. 푸시 클릭 이벤트를 수집

유저가 푸시를 클릭했을 때 푸시 클릭 이벤트를 업로드하고, onCreate 또는 onNewIntent에서 푸시 파라미터를 가져올 수 있습니다.

private void Start()
{
     // FCM 메시지 위임 이벤트의 등록
    Firebase.Messaging.FirebaseMessaging.MessageReceived += OnMessageReceived;
}

public void OnMessageReceived(object sender, Firebase.Messaging.MessageReceivedEventArgs e)
{
     // 푸시 이벤트 전송 (TETrackMessageReceived를 참조)
    this.TETrackMessageReceived(e.Message.Data);
}

# 3.3. 푸시 메시지 처리

  • 일반 파라미터: handleTEPushAction메소드를 호출합니다.
  • 패스스루 파라미터: handleTEPassThroughAction메소드를 호출합니다.
private void Start()
{
     // FCM 메시지 위임 이벤트의 등록

    Firebase.Messaging.FirebaseMessaging.MessageReceived += OnMessageReceived;
}

public void OnMessageReceived(object sender, Firebase.Messaging.MessageReceivedEventArgs e)
{
    //일반 파라미터 (TEHandlePushAction을 참조)
    this.TEHandlePushAction(e.Message.Data);
    //파라미터 통과

    this.TEHandlePassThroughAction(e.Message.Data);
}

# 부록:

# 클라이언트가 받은 푸시 파라미터 예

{
    "te_extras": {
         //푸시 클릭의 점프 방법

        "ops_loading_type": "OPEN_APP",
         //파라미터 통과

        "passthrough_params": {
                "param1": "abc",
                "param2": 101,
                "param3": [{
                        "subText1": "xyz",
                        "subText2": 2
                }]
        },
         //TE운영 모듈의 수신 속성

        "#ops_receipt_properties": {
                "ops_task_id": "0082",
                "ops_project_id": 1,
                "ops_task_instance_id": "0082_20230331",
                "ops_push_language": "default",
                "ops_task_exec_detail_id": "55"
        }
    }
}

# TETrackMessageReceived

private void TETrackMessageReceived(IDictionary<string, string> data)
{
    //FCM 메시지를 TE 시스템에
    Dictionary<string, object> te_extras = ThinkingAnalytics.Utils.TD_MiniJSON.Deserialize(data["te_extras"]);
    Dictionary<string, object> properties = new Dictionary<string, object>();
    if (te_extras.ContainsKey("#ops_receipt_properties"))
    {
        properties.Add("#ops_receipt_properties", te_extras["#ops_receipt_properties"]);
    }
    ThinkingAnalytics.ThinkingAnalyticsAPI.Track("ops_push_click", properties);
    ThinkingAnalytics.ThinkingAnalyticsAPI.Flush();
}

# TEHandlePushAction

private void TEHandlePushAction(IDictionary<string, string> data)
{
    Dictionary<string, object> te_extras = ThinkingAnalytics.Utils.TD_MiniJSON.Deserialize(data["te_extras"]);
    string type = te_extras["ops_loading_type"].ToString();
    if ("OPEN_APP".Equals(type))
    {
        // TODO 앱의 메시지를 여는 처리 → 앱을 실행해주세요
    }
    else if ("OPEN_URL".Equals(type))
    {
        string url = te_extras["ops_url"].ToString();
        if (!string.IsNullOrEmpty(url))
        {
            // TODO URL을 처리하다 →  URL의 처리를 해주세요
        }
    }
    else if ("CUSTOMIZED".Equals(type))
    {
        string custom = te_extras["ops_customized"].ToString();
        if (!string.IsNullOrEmpty(custom))
        {
          // TODO 사용자 정의 메시지를 처리 → 사용자 정의 메시지를 처리해 주세요
        }
    }
}

# TEHandlePassThroughAction

private void TEHandlePassThroughAction(IDictionary<string, string> data)
{
    Dictionary<string, object> te_extras = ThinkingAnalytics.Utils.TD_MiniJSON.Deserialize(data["te_extras"]);
    string params = te_extras["passthrough_params"].ToString();
    //params는 파라미터를 패스스루합니다. 다음에 구체적인 업무 로직을 실행합니다.
}