43 comments

[ 3.4 ms ] story [ 93.7 ms ] thread
Really proud of the entire team on getting us here! Happy to answer any questions you guys have.
Way to go guys! Keep up the great work and momentum.
Went through their iOS SDK. What's up with people shoving so much shit into their public facing API (the interface). I don't need all those comments if you could name your selectors properly (which you did)

You took a file that could be visible on my 13" and made it huge and bloated.

Still going through the implementation but there are a few flags. (Will do issues or PRs)

Yes I am bored and caffeinated at 11 pm.

Sorry for being overly negative, you did actually have cool stuff that Mixpanel missed out on. Like giving actual readable device names.

Thanks for taking a look at our SDK. We actually put in all the comments on the interface file to clear up confusion people had when using the API.
Yeah I figure, but notice how Apple keep their documentation outside of their interface file. Try that. It makes it easier to learn.
You probably want to do three things

1) Extract all network layer into its own stuff. We built an SDK recently, and I decided to make three layers out of it. SDK -> OAuth2 -> Networking

2) Separate that 1000 lines of code into several classes (check #1)

3) Update your device naming https://github.com/seivan/mixpanel-iphone/blob/feature/prope...

You guys will run into a case where your users will pollute their tracking with unknown model names because your SDK was outdated on the naming.

Even if they do update the SDK, the users will have ton of data with the old naming.

I'd probably store the device naming map on the server side in case of new devices without having to update the SDK.

Also, write tests, add a sample app, add your cocoapod spec file to your repo as well - etc.

Thanks for the suggestions!

We're on cocoapods, have tests, and a sample app locally but haven't pushed all that to Github to keep things simple for everyone looking at the source.

Model name tracking is an issue- we've fixed it in our backend so we can remap unknown names to display the correct thing on our website interface. We just haven't yanked the code from the SDK.

Agree on rearchitecting it with separation of concerns. We have to be very careful with any changes we push. The code's already running successfully on 10MM phones without any issues and we have to make sure not to introduce any new ones- so that process takes a while. Thanks again!

If you have a complete suite of unit tests, integration tests and system tests, you should not have fear on refactoring your code.

Question: do you store events that could be not send in a persistent store to retry at a later stage ?

It's true that tests are very helpful for this. However there are a lot of bugs in the wild that are difficult to reproduce, especially ones that will only crop up under rare conditions of state. It's as Linus said- "There really are only two acceptable models of development: think and analyze or years and years of testing on thousands of machines". Years and years of testing on thousands of machines happens to be the best predictor of code that runs correctly.
[Amplitude generateRandomId]; --> is that persistent per device ?
It's persistent across app opens, not across installs though. We were using AdvertiserID for tracking but Apple started clamping down on that so we've switched over to to vendor ID, which they explicitly recommend for things like this.
Ok, and next question: logRevenue why only accept dollar ? This puts the burden of estimating dollar revenue received from different currencies on your customer. ( which is a common case for global mobile apps... )
It's not a dollar amount, but any NSNumber value. We'll provide support for localization down the line.
setUserId --> do you propagate the user id backwards to events of the same session that were sent before the user id was set ?
Yes, we tie the two data sets together.
Cool, that can save a lot of headaches.
> You took a file that could be visible on my 13" and made it huge and bloated.

You're angry about this? https://github.com/amplitude/Amplitude-iOS/blob/master/Ampli...

Selector naming isn't a replacement for documentation, unless you happen to know how to express invariants like these entirely through naming and the type system:

"Property keys must be <code>NSString</code> objects and values must be serializable."

Also, I think the problem you might be having is that you're trying to hold other people's software to the constraints of your particular way of using a 13" consumer laptop.

GitHub Feature request? (Remove commented lines checkbox)
Was excited after visiting that landing page, but woof on the pricing.

We do custom app development for a variety of large companies, so do hear "analytics, analytics, analytics" all the time. But I would just hear "go with Google Analytics" at those prices.

We're actually cheaper than Google Analytics at really large scale. One of our most recent customers was recently forced upgrade to Google Analytics Premium because they were tracking too much data and decided to come to us instead because we were cheaper.
The mobile analytics ecosystem is in need of an overhaul. None of the existing players offer a great solution, least of all Flurry. Really excited to see how much further Amplitude can take things.
I'm curious, what is it that Flurry does not do well? Most of our customers are very happy.
I'm not OP, but I do have a question I've been trying to get answered from Flurry for over a year. How do I see breakdowns of properties I set on events? I can't find any way to do this in the Flurry reporting dashboard. Mixpanel brings this information front and center.
Sorry for the delay, I must have missed this one. If you go to Events and select the event you are interested in, there will be a Pie Chart icon that allows you to click through to the properties data.
Site is down :(
Affected by the Namecheap DDOS today unfortunately. Just switched over to Amazon Route 53 but it's taking a while to propagate to everyone.
Thanks. works again.
Amplitude (YC W12) vs Mixpanel (YC S09)
Are there any good iOS analytics that break out the non-US markets? How well is Apple doing in countries like Brazil, South Korea, or Turkey, for example?

Android has 80% of the world market so it's tough to know where iOS has significant market share.

If you're curious about it for your own iOS app, we have that data for you. We keep all app data private to the app developer though, so we can't share aggregate statistics.
Can you explain your policy on using and sharing aggregate statistics? Your privacy policy allows you to collect them but from my quick glance I hadn't realised you didn't share them.
We don't share data to any third parties. We do look at aggregate traffic internally to ensure we can meet demand. We also will go into people's accounts if they ask us to for support. I'll make that more explicit in our policy.
Great, I will probably give you a try when I get a chance.
I'd like to know which markets are worth translating to. I've done Chinese and Russian and they've done well.
Congrats Spenser, Curtis, and the rest of the team!
I've used Mixpanel for some time. It does most of what it's supposed to but I'm not a huge fan. I can't wait to check them out.
Thanks for taking a look! Email me at spenser@amplitude.com
Super happy customer here. Not many analytics companies give you raw SQL access to your data - it's pretty clutch if ever you need to get insights that you can't get from a service's web dashboard (which is basically all the time if you're doing any serious analysis).
We're really glad to have you as a customer, Siqi!
Yeah yeah, the Android code suffers from the same lack of good OO design/code organization as the iOS code, but frankly it's such a simple sdk, it won't matter until it's feature rich and complicated. Anyways, some immediate concerns as I see it:

1. Sending requests every 10 seconds (and/or at every onPause) is no-good for battery life. Please, let the radio power down once in a while!

2. Using DefaultHttpClient with no connection pooling

3. It's doing a ton of work, allocating objects, logging events, in every onResume/onPause...I don't like this design. That includes when I get a pop-up message from another app, even if I dismiss it immediately.

4. Would be nice to register for activity lifecycle callbacks for api level >= 14, so people can't screw up the implementation.