matomo-org / matomo-sdk-ios

Matomo iOS, tvOS and macOS SDK: a Matomo tracker written in Swift
MIT License
388 stars 164 forks source link

Adding the option to customize the cid of the visitor #259

Closed brototyp closed 6 years ago

brototyp commented 6 years ago

As @mplackowski asked in #258:

It would be great to have both parameters in the sdk. I mean the ("cid" and "uid" keys following this documentation: https://developer.matomo.org/api-reference/tracking-api) In my usecase I need to setup visitorId ("cid" key ) manually after user converts from mobile website to the app.

I'm using branch deeplinks with custom parameters and one of them is the pk_vid from the website. This way it is possible to track users switching from website to the app in a single visit (assuming that the same tracker is used on website and in the app).

Being able to see user flow as a whole is a great feature, since the mobile website in many cases is the real starting point in the conversion funnel.

brototyp commented 6 years ago

@mplackowski If I get your issue correctly, that is exactly what the uid is for. Is there a specific reason why you want to "synchronize" the cid instead of the uid?

mplackowski commented 6 years ago

So the problem with uid is that it can only by used to track some percent of all visitors - they must be logged in.

Considering typical user flow there is no way to track them from the top of the funnel basing on the uid, that is created somewhere in the middle (e.g landing page -> cart -> login -> checkout -> receipt).

I just realized that the _id parameter can be used in the same way as cid - not sure what is the difference between them. In general they both have impact on the log_visit.idvisitor column in DB so I assume it is better to just use the _id since it is already implemented in the SDK.

With this in mind, my idea is to allow overriding the _id parameter. It could be done by making one more public variable in MatomoTracker following the visitorID/userID style: https://github.com/matomo-org/matomo-sdk-ios/blob/develop/MatomoTracker/MatomoTracker.swift#L22

This would probably look like this:

@objc public var clientId: String? {

        get {
            return matomoUserDefaults.clientId
        }
        set {
            matomoUserDefaults.clientId = newValue
            visitor = Visitor.current(in: matomoUserDefaults)
        }
    }

This way the tracker could by updated with new _id paramter as soon as the pk_vid is passed to the app via deeplink. Also such approach allows adding the uid independently.

The final output is that all tracked actions/visits always have consistent records in the idvisitor column and can be joined easily. At the same time, only some visits will provide additional info - if the userid column is non null. But frequently, especially during the first steps in the funnel, records in this column will be null

brototyp commented 6 years ago

@mplackowski Sorry for not replying in quite a while.

There is one downside to this concept. An that is that you "lose your visitor" the moment when you actually set the clientId. It is then counted as a completely new visitor.

I get your point that the user has to be logged, so that one can set the uid to the actual email of the user. One alternative would be to set some unique value to the uid if the user is not logged in. And once the user logs in either change it to the email or store this unique-value alongside with the e-mail so you then have a relation to the actual user.

What do you think about this alternative?

mplackowski commented 6 years ago

There is one downside to this concept. An that is that you "lose your visitor" the moment when you actually set the clientId. It is then counted as a completely new visitor.

So in my scenario I would like to set it in the app before the sdk sends the very first event from that app instance. By default for all organic installs it won't be used at all, but for installs from deeplinks (e.g branch.io links) when the vistor id is passed as a parameter I could store it in user defaults and use for every tracked event. So in current code the _id is autogenerated and then stored as long as the app is installed. My suggestion is to give option to provide such _id and if it is not provided then autogenerate.

brototyp commented 6 years ago

I see your point. What do you think about my proposal / alternative by leveraging the clientId?

mplackowski commented 6 years ago

One alternative would be to set some unique value to the uid if the user is not logged in. And once the user logs in either change it to the email or store this unique-value alongside with the e-mail so you then have a relation to the actual user.

Well in my opinion this approach makes a simple thing quite complicated. At first the vistor is tracked on the mobile website where no login option is available, so with this solution I would need to use the uid already on the mobile websites, then pass the uid to the mobile app and finally keep it somwhere along with the real uid once the user logs in. It is weird flow especially when I know that there is the separate "idvistor" column that stores info about all users on both action and visit levels.

Recently I realized that when Matomo detects uid in the request the _id is completely ignored and to the idvisitor column some hashed value from the uid will be inserted instead. I don't know the details why it works this way, but from my point of view the solution is only one - stop using the uid. Instead I will send user id as custom dimension in visit scope.

Such approach makes the idivistor column values consistent so the pk_vid passed from mobile website will be always respected by server side. Also at the same time I will keep record about logged in users though the reports must be done either by custom segments or by direct queries to DB.

So to sum up, firstly I think that the _id parameter should by customizable so the client sdk can track users from websites ( which is similar to cross domain visitor tracking) and secondly tracking logged in users is performed in a 'very specific' way by Matomo so to keep data clean I will keep uid's in separate dimension

brototyp commented 6 years ago

Hi @mplackowski, thanks a million for your elaborate explanation. I am a little hesitant to let the user change the clientId because there is a little bigger chance of using it in a wrong way and thus losing information. I will check what the backend team thinks about this and will think about what is the best way to do this while reducing the risk of using it wrongly as much as possible.

mplackowski commented 6 years ago

I fully understand your point of view and the responsibility that is necessary here.

In the Android SDK it is possible to access the SharedPreferences and update them before initializing the tracker. I'm not sure it thats the best design but it worked in our usecase.

For my needs I just used the source code with few modifications.

mattab commented 6 years ago

What is the clientId in the iOS SDK?

When it comes to the SDK API here is my suggestion:

Hope this helps?

brototyp commented 6 years ago

Hi @mattab, thanks a lot for your feedback!

Just a short recap of what SDK is currently doing and how things are named:

If I understand you correctly I would change the following.

Thus there can be the case that all three identifiers, _id, cid and uid are set. Is that correct? Please correct me if I am wrong.

mattab commented 6 years ago

Yes, looks correct :+1: FYI: in the PHP SDK we called visitorid the forcedVisitorId to maybe make it a bit more clear.

brototyp commented 6 years ago

Hi @mplackowski,

I just created the PR #271 implementing this feature. If you find some time to review it and check if this solves your issue, it would be really great!

brototyp commented 6 years ago

This got merged and will be part of the next release