CommandersAct / iOSV5

Other
7 stars 2 forks source link

How to migrate TC_UNIQUEID from SDK v4.x to SDK v5.x? #13

Open pyby opened 10 months ago

pyby commented 10 months ago

In the 5.4.2 release notes, https://github.com/CommandersAct/iOSV5/releases/tag/5.4.2, mentioned to new functions and the legacy TC_UNIQUEID.

We made tests from our app in SDK v4.4.1 to SDK v5.4.2, I can't find the TC_UNIQUEID value from the form data (v4.x) in the json payload (v5.x).

Example with an app in the iPhone 14 Pro iOS 16.4 simulator:

Do I miss something?

  • Added 2 function to use legacy ID TC_UNIQUEID to ensure continuity for the old clients still using it. Are there public and what are their names?

Does a migration code coud be done by the SDK from user default tc_unique_id property to the new property also in user default #TC_SDK_ID#? On server side, destinations uses now device.sdk_id, but it's a new UUID, not the same UUID.

The what's new looks interesting. Could you share a documentation or an how to?

pyby commented 10 months ago

Got it. iOS: https://github.com/CommandersAct/iOSV5/blob/master/TCServerSide/README.md#useful-methods Android: https://github.com/CommandersAct/AndroidV5/blob/master/TCServerSide/README.md#useful-methods

iOS TCPredefinedVariables:

- (void) useLegacyUniqueIDForAnonymousID;
- (void) useLegacyUniqueIDForConsentID;

~But sadly, those 2 methods are only in the TCServerSide.framework , not also in the TCServerSide_noIDFA.framework. We use the No IDFA one.~

~Could you please add it also for TCServerSide_noIDFA.framework? Sadly, we discover 5 days before our official update release 🙃~

Why the SDK didn't migrate the UUID value itself? Too old property or not enough anonymous?

useLegacyUniqueIDForAnonymousID method does not change device.sdk_id value, but user.consistent_anonymous_id.

What do you recommend for a mapping server side for a unique id now? device.sdk_id or user.consistent_anonymous_id?

CommandersAct commented 10 months ago

Hello ! We're actually using the old code which was still inside the SDK but it was a very old one and nearly not used anymore.

useLegacyUniqueIDForAnonymousID method does not change device.sdk_id value, but user.consistent_anonymous_id.
Indeed we were asked to be able to use this value to recognize a client thus a user.

But if you want to do otherwise you can still use TCPredefinedVariables -> getUniqueIdentifier are still available on both platforms and device.sdk_id is a public parameter you can change it as you see fit.

What do you recommend for a mapping server side for a unique id now? device.sdk_id or user.consistent_anonymous_id?

I can't really recommand anything this will depend on the destinations you are using and I'm not familiar with their code anyway.

pyby commented 10 months ago

Thank you for the answer.

Our goal would be to use TC_UNIQUEID value only for existing installed apps with a TagCommander SDK v4.x, and not use it for new installed application. Is there a way to do it with SDK methods? Our current patch uses TC_UNIQUEID value in any cases.

TCDevice.sharedInstance().sdkID and TCUser.sharedInstance().anonymous_id look editable. both. Even if the documentation has a definition: https://doc.commandersact.com/developers/tracking/about-events/mobile-sdk-event-specificity#context-greater-than-device

If I understood correctly, this is not the SDK responsibility to do the migration from v4 to v5, but the application rsesponsablitly. Strange point of view and its responsibility. Is that correct?

I'll ask consultant and data engineers for the mapping. I agree, it's looks more about the Destinations choice. A built destination looks to use device.sdk_id, like MAPP one.

CommandersAct commented 10 months ago

TC_UNIQUEID is the key inside which we store the ID, you could probably check with TCSharedPreferences.retrieveInfoFromSharedPreferences("TC_UNIQUEID", appcontext) if it is already saved or not but before initializing the SDK.

If I understood correctly, this is not the SDK responsibility to do the migration from v4 to v5, but the application rsesponsablitly. Yes sadly it has been done like this because TC_UNIQUEID was outdated by the SDK_ID for a long time.

pyby commented 10 months ago

Thank you for your shared information.

We didn't follow the migration from TC_UNIQUEID to SDK_ID before the migration from SDK v4 to V5. We used a v4.4.1 custom SDK before. Linked to our open source PR on PlaySRG-Apple project the code gets the TC_UNIQUEID value. We did the same for Android app, as you shared.

CommandersAct commented 10 months ago

Hello ! I think I misunderstood something. Have you been able to use the TC_UNIQUEID or not at the end?

pyby commented 10 months ago

SRG data analytics trust the value from TC_UNIQUEID property in Commanders ACT SCK v4. This value is used to create events bucket for one "visitor". For the tool they used, MAPP, it's a "blob" id as a string, without any logic inside (named ceid).

The request is for Commanders Act product (SDK v5 and server side v2):

  1. For existing installed applications using SDK v4, keep sending the same value with the updated SDK v5, in device.sdk_id property or an other property.
  2. For new application installations, create a new value the way Commanders Act recommend, in device.sdk_id property or an other property.

The server v2 documentation and your consultant colleagues use the device.sdk_id property for the official Destination Mapp, used by SRG data analytics. That's why device.sdk_id property looks the good candidate, but maybe someone has a better solution.


A test has been done in one SRG project only:

if let tcUniqueID = TCPredefinedVariables.sharedInstance().uniqueIdentifier(), !tcUniqueID.isEmpty {
             TCDevice.sharedInstance().sdkID = tcUniqueID
         }
  1. Not sure it's answer to the 2 points of the request.
  2. It changes the value only "in memory", so the code has to be apply at every launch.
  3. All previous application installations and new installations use the uniqueIdentifier value. Is it recommended by Commanders Acts? As in other methods, the name is LegacyUniqueID.

What is your suggestion, regarding those 2 request points? Shouldn't it be an option proposed by the SDK, to help migration from SDK v4 + server v1 to SDK v5 + server v2?

CommandersAct commented 9 months ago

Understood I'll check if this is possible on our side.

pyby commented 9 months ago

@CommandersAct Thank you.

An other idea we got: Run only one time a value copy.

Using User Default, copy value from "tc_unique_id" property to "#TC_SDK_ID#" property. Save that this copy has been done, s that never executed again.

// Migrate the TC unique id to new sdk id device property.
let tcUniqueId = UserDefaults.standard.string(forKey: "tc_unique_id")
if let tcUniqueId, !tcUniqueId.isEmpty {
    UserDefaults.standard.set(tcUniqueId, forKey: "#TC_SDK_ID#")
    UserDefaults.standard.synchronize()
}

But for that, it would be great that for new installation, no TC unique id creation. And it must be done by the CA SDK, as a client (application) does not know those User Default property keys.

CommandersAct commented 9 months ago

We can't remove the creation of this ID on Android and we need to have a bit of consistency between both platforms. Because on Android it's actually an old system ID which is deprecated btw. So the code only read this value and put it inside the TCUser or doesn't do anything with it.

Do you really need to override the value of TC_SDK_ID ?

if you don't use anywhere else (and maybe even if you do) I think it's better to only set it inside TCUser.anonymous_id. In both case you will need to call a function like "useLegacyUniqueIDForOldUsers" before sending any events. (and this method will test on Android if the UNIQUE_ID is still available)

pyby commented 9 months ago

Thank you for your inputs. We are agree to have consistence between iOS and Android.

As I understood, useLegacyUniqueIDForAnonymousID checks if a unique id exist. That I think the need of SRG data analytics: keep the same id if sent before with SDK v4.

One SRG application currently overrides device._sdk_id because it's asked by the implementation in the server v2 and its requests.

Commanders Acts is a global solution, with mobile SDK, a server, and destination components proposed on the server v2 to connect to other services and map properties. By default, it's this property used to have "a track id to link events together". It would be great that both in the mobile SDK, and on the server, documentions could have a section to help integrators on mobile and on the server.

For next step: If useLegacyUniqueIDForAnonymousID checks the old id value exist and set to TCUser anonymous id (user.consistent_anonymous_id if I checked correctly), we need to ask Commanders Act server v2 consultants and/or Commanders Act server developers to update MAPP Destinations so that Mapp ceid is mapped to this property. But if not possible, maybe the SDK client solution should have useLegacyUniqueIDForSdkID method.

EDITED: Fixed typo after SRG data analytics message reviews.

CommandersAct commented 9 months ago

We've been searching desperatly for a variable not used in v5 anymore AND saved in the sharepreferences but we didn't find any.

We can offer a function inside TCDevice that takes a "v4-to-v5" timestamp and check if the "first_visit" we saved is prior to this date. Which would mean that the current app was at some point upgraded from our old SDK.

In this case, we replace device.sdk_id by unique_ID otherwise we keep the new SDK_ID.

Does this sound correct for your usecase?

pyby commented 9 months ago

Thanks for searching a solution. Maybe an iteration:

I don't understand which timestamp to set, as an integrator: release date is known, but installation date and first run with this new version is unknown.

CommandersAct commented 9 months ago

Sorry too many things going on at the end of the year and not many ppl available.

The issue is that we really don't store anything differently between v4 and v5 that's why we came up with the idea of the timestamp. If you go from 4 to 5 we could check your estimated release date with the first_visit of the app. If the first visit is lower that would mean it's probably from the v4. That doesn't work if you already released part of your app tho :(

Thinking back on your idea I thought that we could not know if it's a new v5 install or an upgrade. The parameter will never be set in either case and I'm not sure if you can call it only when it's an upgrade.