segmentio / analytics-ios

The hassle-free way to integrate analytics into any iOS application.
https://segment.com/libraries/ios
MIT License
401 stars 334 forks source link

Accessing anonymousID #928

Closed xavierjurado closed 4 years ago

xavierjurado commented 4 years ago

What's the recommended approach to access Segment's anonymousID without incurring in the NSCAssert if the SDK is not yet fully initialized?

Use case 1: We want to send the user's anonymousID alongside every network request to our backend. We will use it to fire server-side analytics events for anonymous users.

Use case 2: Some integrations like Optimizely Full Stack expect a userID to be passed to their SDK. For an anonymous user the documentation recommends sending Segment's anonymousId, but we cannot safely do so due to the aforementioned NSCAssert.

In either case we cannot wait for SEGAnalyticsIntegrationDidStart notification because we need to fetch anonymousId early in the application lifecycle.

bsneed commented 4 years ago

Hi @XavierAgostini, what version of Analytics-iOS are you using?

xavierjurado commented 4 years ago

3.8.0 @bsneed

bsneed commented 4 years ago

@xavierjurado I just pulled 3.8.0, and I'm not seeing an NSAssert in this path calling SEGAnaytic's getAnonymousID. Can you show me where/what you're seeing?

xavierjurado commented 4 years ago

Sure, the assert is located in the singleton's accessor method:

https://github.com/segmentio/analytics-ios/blob/master/Analytics/Classes/SEGAnalytics.m#L512-L516:

+ (instancetype)sharedAnalytics
{
    NSCAssert(__sharedInstance != nil, @"library must be initialized before calling this method.");
    return __sharedInstance;
}
bsneed commented 4 years ago

Ah, I see. You've got to init the library before it would possibly have an anonymousID. Just verified this works.

SEGAnalytics.setup(with: configuration)
let anonId = SEGAnalytics.shared()!.getAnonymousId()
print("%@", anonId)

Are you guys doing something different?

xavierjurado commented 4 years ago

You are absolutely right @bsneed. For some reason I thought we needed to wait for the SDK to be fully initialized before we could invoke getAnonymousId() but that doesn't make any sense. As soon as you invoke SEGAnalytics.setup you are good to go. Thanks!

Somewhat related question: is there a way to fetch the user traits dictionary from outside the framework? It's related to the second use case, we need the traits to pass them to Optimizely SDK so it can device whatever a user belongs to an audience or not.

bsneed commented 4 years ago

@xavierjurado no problem! To get the traits, you could write a middleware to pick them up as they're set, but I think that's probably the extent of it for now. We could add this for you, but it'd be in the 4.x betas.