While grouping your events by an event or user property, you may have noticed that some of your results have been sorted into a group called '(none)'. '(none)' on Amplitude represents null. But why do some of your users have null event or user property values?
This article will go over some of the common reasons why your users have null and unexpected property values.
Table of Contents
Event property values are unique by event. If you send an event with a null value at the time of the event, grouping by that event property will sort some events/users into the '(none)' bucket.
As an example, let's say User A fired "Send Message" once on January 1st and once on February 1st. The 'Audience' event property was instrumented on January 15th, and this property can only have values equal to 'Default' and 'Mentioned_Contacts.' When User A fired "Send Message" on February 1st, it had an event property of 'Audience = Default.'
How will User A be counted in the chart below?
User A will be counted once in the 'Default' bucket and once in the '(none)' bucket. User A had 'Audience = Default' at the time of the February 1st event, and 'Audience = (none)' at the time of the January 1st event.
When results are measured by Uniques, users are deduplicated within each unique bucket. This means that if User A fired "Send Message" where 'Audience = Default' on February 1st and February 2nd, User A will still be counted only once in the 'Default' bucket above.
The same logic applies when you send non-null event property values. Events and users will be sorted according to the property value that was sent at the time of the event.
User property values can be unique by event and they can change overtime. They are stored on a separate table and applied to events according to the process described here. When a user's user property values update, the user property values attached to historical events will not change.
The custom user properties attached to your users' events will reflect the user property values present at the time of the event.
As an example, let's say that you've instrumented a user property type called 'Account_Type' on January 15th. User A is a registered user who has an account type of 'Shopper,' and she fired "Add Item to Cart" once on January 1st and once on February 1st.
How will User A be counted in the chart below?
Because the 'Account_Type' user property was not instrumented until January 15th, all events fired prior to January 15th have a null value for 'Account_Type.' User A will be counted once in the '(none)' bucket and once in the 'Shopper' bucket.
When results are measured by Uniques, users are deduplicated within each unique bucket. This means that if User A fired "Add Item to Cart" on February 1st and February 2nd, User A will still be counted only once in the 'Shopper' bucket above.
This same logic pertains when you send non-null user property values. Events and users will be sorted according to the property value that was applied at the time of the event.
We have this logic implemented because user attributes can change over time. 'City', for example, is an attribute that can change by the hour as users travel to different cities and fire events there. Understanding where the user was located at the time of the event can be more valuable than understanding where the user was most recently located.
Location user properties (such as '[Amplitude] City', '[Amplitude] DMA', '[Amplitude] Region', and '[Amplitude] Country') are determined by GeoIP. We use MaxMind's database, which is widely accepted as the most reliable digital mapping source, to lookup location information from the user's IP address.
For client-side events, location properties can have '(none)' values if MaxMind returns null for that IP address. Even through MaxMind is considered as the most reliable source, accuracy and availability of city/region information can vary by country (more info here).
For server-side events, location property values are determined either by GeoIP (which falls back on location_lat' and 'location_lng' if unavailable) or explicitly defined in your API call. Our HTTP API allows you to send custom 'City', 'DMA', 'Region', and 'Country' values with your events. If you choose to send 'City', 'DMA', 'Region', and 'Country' values, Amplitude will not modify them to reflect GeoIP. However, please be sure to update all four fields together; setting any one of these fields will automatically reset all others (see Footnotes 3 here).
Amplitude determines '[Amplitude] Device family' and '[Amplitude] Device type' by grabbing 'device_brand', 'device_manufacturer', and 'device_model' strings directly from your user's device and then mapping these strings to our repository of device types.
With each new phone model that comes out globally, there may be some device types that have not yet been mapped. In these cases, '[Amplitude] Device type' will be '(none)'. For context, as of 2015, Android has more than 24,000 unique devices (both tablets and smartphones); so it's very difficult for Amplitude to proactively search globally for all new devices that are being released. If there is a missing mapping that you wish to see, please reach out to us at firstname.lastname@example.org and we'll add it to the list!
Outside of device mapping, server-side events may also have null device information if these fields (platform, os_name, os_version, device_brand, device_manufacturer, device_model, and carrier) were not updated together. Setting any of these fields will automatically reset all of the other property values to null if they are not also explicitly set for the same event (see Footnotes 2 here).