Hello!
We are developers (proudly sounds, isn’t it?), And we are actively sawing new features, fixing bugs and trying to make our product better. But in order to understand exactly how the user uses our product, which product chips he likes, and which ones - not so much, we use analytics. There are many different means, but in this article I would like to talk about Google analytics, which is actively developing and changing. An old watchman named Google Analytics is replacing a new fighter - Google Analytics for Firebase (nee - Firebase Analytics).
Even in the names you can catch this wind of change. And the wind of change always generates a certain informational vacuum, into which various rumors get, far from always reliable at the same time.
Therefore, let's try to understand in detail, and what is now with this analytics, what to use in the end. And how do you continue to live?
If there is a lot of information about Google Analytics, and it is systematized (which only this resource costs, an ideal reference), then Google Analytics for Firebase has a typical illness of a young and actively developing product - there is little information, it is fragmented and sometimes even contradictory. And I once spent a lot of time and effort to figure out what was happening.
Actually the main goal of this article is to systematize the knowledge and current state of Google Analytics for Firebase. Some roadmap for Google Analytics for Firebase.
I am sure this “card” will save you a lot of time and nerves =)
I'll start all the same with the hottest.
It seems to me that this rumor has been going since Firebase Analytics. And on the one hand, it is logical, why Google has two analytics tools. But Google Analytics (we will call it GA) and Google Analytics for Firebase (we’ll call it FA in the old manner) are two analysts with different concepts and approaches, which we’ll talk about below.
GA will not go anywhere and will not disappear (at least for now), and also will not be absorbed by someone. This is both information from representatives of the Moscow office of Google, and insiders from the developers themselves.
GA fans can sleep well ... for now. But who knows what will happen next. Therefore, I strongly recommend to continue reading =)
FA is an analyst with a completely different concept and philosophy. It is event based and is intended solely for mobile phones. Whereas GA is screen-based and at first it was for the web, and only then it was finished for mobile.
GA is structured around hierarchical events with a single value, FA is more about recording a single event with a large number of parameters (key-value pairs).
These analysts are very different. And therefore they cannot be interchangeable.
Migration from one to another is not provided. But Google is working on a certain compatibility of these analytics, which we will also talk about later.
Kohl, we have touched on the theme of events. In terms of understanding the “events” GA and FA are really very different. And this is especially noticeable by example.
Let's say your application is a game. At the end of the game you want to send statistics, as a result the user played. And you want to know the total score of the user, the number of enemies killed and the number of rounds passed.
In GA, it will look something like this:
// total score mTracker = googleAnalytics.newTracker(R.xml.tracker_global_config); HitBuilders.EventBuilder builder = new HitBuilders.EventBuilder() .setCategory("gameOver") .setAction("totalScore") .setLabel("") .setValue(gameStats.getTotalScore()); mTracker.send(builder.build()); // enemies beaten mTracker = googleAnalytics.newTracker(R.xml.tracker_global_config); HitBuilders.EventBuilder builder = new HitBuilders.EventBuilder() .setCategory("gameOver") .setAction("enemiesBeaten") .setLabel("") .setValue(gameStats.getEnemiesBeaten()); mTracker.send(builder.build()); // roundsSurvived mTracker = googleAnalytics.newTracker(R.xml.tracker_global_config); HitBuilders.EventBuilder builder = new HitBuilders.EventBuilder() .setCategory("gameOver") .setAction("roundsSurvived") .setLabel("") .setValue(gameStats.getRoundsSurvived()); mTracker.send(builder.build());
In GA, each event is essentially a hierarchy of parameters:
category -> action -> label -> value
And in the console itself, you could observe this hierarchy of parameters. Actually, when inventing events that you would like to follow, you should have been guided by this paradigm. Also in the console, you can build various filters on these parameters.
But in GA in terms of events there is a small minus. If you want to add additional parameters to the event, besides the ones mentioned above, here you have to dance around "category" -> "action" -> "label" -> "value", invent new wordings and so on. Inconvenient. At least it was before.
And now let's see how to beat these statistics with the FA:
Bundle params = new Bundle(); params.putLong("totalScore", gameStats.getTotalScore()); params.putLong("enemiesBeaten", gameStats.getEnemiesBeaten()); params.putLong("roundsSurvived", gameStats.getRoundSurvived()); mFirebaseAnalytics.logEvent("game_over", params);
As you can see, instead of three events we send one that is more logical and convenient. About the "events" in the FA, we'll talk in more detail below.
The second thing that analysts differ much from is the console.
This is how the console looks like in GA (the image is clickable ):
“Events” are hidden deep in the “Behavior” tab on the left. But the standard report immediately breaks down into Category, Action, Label ( clickable image ):
This is what the FA console looks like ( clickable image ):
The first thing you see is the "Summary." And I would immediately pay attention to the User engagement card ( clickable image ):
Finally, a normal screen view was added to the FA-console. Until May, we lived without it. That is, the event “user engagement” was sent, but it could not be seen in the console at all. It was terrible. And this is probably one of the reasons why nobody wanted to switch to FA.
As you can see, the Events tab goes right behind the Dashboard , which confirms once again - the FA is sharpened to work with events. We will also return to the console a little later, and now I propose to dive into this vast theme of “Events” in the FA.
Let's take a quick look at the code:
Bundle bundle = new Bundle(); bundle.putString(FirebaseAnalytics.Param.ITEM_ID, id); bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, name); bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, "image"); mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.SELECT_CONTENT, bundle);
You can send up to 500 different types of events in your application, including the preset ones ( FirebaseAnalytics.Event.SELECT_CONTENT
is preset, but you can also set your own types). The total number of events sent is not limited ( source ).
Up to 25 parameters can be attached to each event (what goes into the Bundle
). The parameters are also predefined, but nobody forbids you to set custom parameters. Described here .
Types of events and parameters are ordinary String
.
Event and parameter names are case sensitive. Identical events must match in type and parameters.
In addition, there are events that are sent by default. The entire list of automatically sent events with the description is given on this link . As you can see, there are a lot of really interesting events that we previously could not get. Cool!
You can also read through the link above which predefined events and parameters can be selected for certain events.
You noticed that there is a lot of suspicious talk about predefined event names and parameters. And in illustrative examples, such events are usually sent with parameters. And this is no accident. Suppose you send an event with ten custom parameters. And then in the console for your event, you will see the following ( clickable image ):
“But where are all my parameters?” You ask. And they are not on the console, so here.
The fact is that all beautiful graphics and stuff are built only if you use predefined names. Use your "custom", you will not see anything at all. Only “number of events” and “number of users”.
And before I / O 17 it was a terrible pain. Graphs could be built by playing, for example, with the Value parameter, as in this article . But this, of course, is not that.
And here, of course, it’s time to remember GA, where everything is for people, building filters there for anything and as much as you want.
But here a little ambush. Standard reports - yes, build without problems. But in most cases we need custom reports. For example, add a second dimension to sort events by device model. And here comes the terrible word "Sampling" .
Depending on the report, the GA sampling algorithm is different. How exactly the sample is considered for each report is not revealed by Google, but in general, all practices are already known. This is usually hi-based-sampling or cookie-based-sampling . In the first case, random sampling is taken from all records (events, views, etc.), in the second case random sampling is taken for all users (marked cookies or gaid / idfa, if this is a mobile application).
Therefore, it is impossible to reliably talk about the error for each field.
In practice, it is said that when sampling more than 5%, the error in absolute numbers in the reports on events was less than 2.5%.
For providing information on sampling, I would like to express my gratitude to Alexander Sergeyev from Yandex.
Yeah. Everything is not easy with these "Events". And in fact, the FA is going to meet the wishes of the common people.
First, there is no sampling in the FA. All data is available there.
And this is very cool, since the cost of Google Analytics 360 (GA paid version without sampling) is rather big. And in FA, you can upload your data to BigQuery and do whatever you want with it.
Secondly, after I / O 17, it became possible to build reports on custom parameters.
You are directly on the screen of a specific event are invited to register custom parameters ( clickable image ):
But note that in total for this application you can register up to 50 such parameters ( 10 text and 40 numeric ). I tried life hacking to circumvent this restriction: I registered custom parameters with the same name for different events. It did not help, it is still done "plus one".
In addition, if you expect to see immediately ready reports, I hasten to disappoint you. Reports are built cumulatively. Suppose you have an "event_1" with a custom parameter "custom_1" for which you want to build a report. In the console, you set up to build this report at time X. So, all event_1 events that come after time X will be included in the report. Unfortunately, all event_1s up to time X will not be processed. So be careful.
That is, it seems to be better, but not much. What else is offensive, you can not somehow combine these reports with each other. But perhaps we want too much from the console. If you want to do anything with data, then welcome to the wonderful world of BigQuery. Let us slightly open this veil of the mystery of data.
BigQuery is generally a slightly different galaxy.
It was possible to work with BigQuery through GA, but only if you have a premium mode. In FA, you are invited directly to the Events tab to establish a connection ( clickable image ):
Google says: “We give you a car, but you pay for gas”. Tariff plans are available here , and even better here . But believe me, just to try it, the free Blaze tariff limits will be enough for you. And even when working with combat products, judging by the reviews of comrades, the fee is very conditional.
So, let's get acquainted. This is what the BigQuery console looks like ( clickable image ):
In the left menu is a list of available data. For example, TestStep is my test project with one application in it. And bigquery-public-data and Public Datasets are, as you might guess, public data with which you can experiment and on which you can practice writing queries.
On the right, you see a list of requests, both successful and not so.
Now let's take a look at the test application data for March 14, 2017 (table app_events_20170314, clickable image ):
In the table I transferred all the data per day (52 events). The overall composition of the table is presented in front of you. As you can see, here each event is described as fully as possible, including all properties , which will be discussed below.
Let's look at the data preview (Preview tab, clickable image ):
The tabular view of the move is uninformative. A much more understandable form is JSON ( clickable image ):
And then our event is presented in full. For some reason, it is impossible to expand the display of json in UI for some reason, so I’ll bring the full json of the last five events separately:
[ { "user_dim": { "user_id": null, "first_open_timestamp_micros": "1488878151620000", "user_properties": [ { "key": "first_open_time", "value": { "value": { "string_value": null, "int_value": "1488880800000", "float_value": null, "double_value": null }, "set_timestamp_usec": "1488878151620000", "index": null } } ], "device_info": { "device_category": "mobile", "mobile_brand_name": null, "mobile_model_name": null, "mobile_marketing_name": null, "device_model": "507SH", "platform_version": "6.0.1", "device_id": null, "resettable_device_id": null, "user_default_language": "ru-ru", "device_time_zone_offset_seconds": "10800", "limited_ad_tracking": "false" }, "geo_info": { "continent": "Europe", "country": "Russia", "region": "Moscow", "city": "Moscow" }, "app_info": { "app_version": "1.0", "app_instance_id": "d0c587de4d5804ddc1d34f8d54b981f9", "app_store": "manual_install", "app_platform": "ANDROID", "app_id": "com.example.matsyuk.testfirebase" }, "traffic_source": null, "bundle_info": { "bundle_sequence_id": "65", "server_timestamp_offset_micros": "-496748" }, "ltv_info": null }, "event_dim": [ { "date": "20170314", "name": "user_engagement", "params": [ { "key": "firebase_screen_class", "value": { "string_value": "SecondActivity", "int_value": null, "float_value": null, "double_value": null } }, { "key": "firebase_event_origin", "value": { "string_value": "auto", "int_value": null, "float_value": null, "double_value": null } }, { "key": "firebase_screen_id", "value": { "string_value": null, "int_value": "1109587836504693342", "float_value": null, "double_value": null } }, { "key": "engagement_time_msec", "value": { "string_value": null, "int_value": "4424", "float_value": null, "double_value": null } } ], "timestamp_micros": "1489478210462000", "previous_timestamp_micros": "1489478205970000", "value_in_usd": null } ] }, { "user_dim": { "user_id": null, "first_open_timestamp_micros": "1488878151620000", "user_properties": [ { "key": "first_open_time", "value": { "value": { "string_value": null, "int_value": "1488880800000", "float_value": null, "double_value": null }, "set_timestamp_usec": "1488878151620000", "index": null } } ], "device_info": { "device_category": "mobile", "mobile_brand_name": null, "mobile_model_name": null, "mobile_marketing_name": null, "device_model": "507SH", "platform_version": "6.0.1", "device_id": null, "resettable_device_id": null, "user_default_language": "ru-ru", "device_time_zone_offset_seconds": "10800", "limited_ad_tracking": "false" }, "geo_info": { "continent": "Europe", "country": "Russia", "region": "Moscow", "city": "Moscow" }, "app_info": { "app_version": "1.0", "app_instance_id": "d0c587de4d5804ddc1d34f8d54b981f9", "app_store": "manual_install", "app_platform": "ANDROID", "app_id": "com.example.matsyuk.testfirebase" }, "traffic_source": null, "bundle_info": { "bundle_sequence_id": "64", "server_timestamp_offset_micros": "-515257" }, "ltv_info": null }, "event_dim": [ { "date": "20170314", "name": "user_engagement", "params": [ { "key": "firebase_screen_class", "value": { "string_value": "MainActivity", "int_value": null, "float_value": null, "double_value": null } }, { "key": "firebase_event_origin", "value": { "string_value": "auto", "int_value": null, "float_value": null, "double_value": null } }, { "key": "firebase_screen_id", "value": { "string_value": null, "int_value": "1109587836504693341", "float_value": null, "double_value": null } }, { "key": "engagement_time_msec", "value": { "string_value": null, "int_value": "17278", "float_value": null, "double_value": null } } ], "timestamp_micros": "1489478205970000", "previous_timestamp_micros": "1489153178047000", "value_in_usd": null } ] }, { "user_dim": { "user_id": null, "first_open_timestamp_micros": "1488878151620000", "user_properties": [ { "key": "first_open_time", "value": { "value": { "string_value": null, "int_value": "1488880800000", "float_value": null, "double_value": null }, "set_timestamp_usec": "1488878151620000", "index": null } } ], "device_info": { "device_category": "mobile", "mobile_brand_name": null, "mobile_model_name": null, "mobile_marketing_name": null, "device_model": "507SH", "platform_version": "6.0.1", "device_id": null, "resettable_device_id": null, "user_default_language": "ru-ru", "device_time_zone_offset_seconds": "10800", "limited_ad_tracking": "false" }, "geo_info": { "continent": "Europe", "country": "Russia", "region": "Moscow", "city": "Moscow" }, "app_info": { "app_version": "1.0", "app_instance_id": "d0c587de4d5804ddc1d34f8d54b981f9", "app_store": "manual_install", "app_platform": "ANDROID", "app_id": "com.example.matsyuk.testfirebase" }, "traffic_source": null, "bundle_info": { "bundle_sequence_id": "63", "server_timestamp_offset_micros": "-500210" }, "ltv_info": null }, "event_dim": [ { "date": "20170314", "name": "ga_event", "params": [ { "key": "label", "value": { "string_value": "label1", "int_value": null, "float_value": null, "double_value": null } }, { "key": "firebase_screen_class", "value": { "string_value": "MainActivity", "int_value": null, "float_value": null, "double_value": null } }, { "key": "action", "value": { "string_value": "action1", "int_value": null, "float_value": null, "double_value": null } }, { "key": "firebase_event_origin", "value": { "string_value": "app", "int_value": null, "float_value": null, "double_value": null } }, { "key": "value", "value": { "string_value": null, "int_value": "1", "float_value": null, "double_value": null } }, { "key": "category", "value": { "string_value": "category1", "int_value": null, "float_value": null, "double_value": null } }, { "key": "firebase_screen_id", "value": { "string_value": null, "int_value": "1109587836504693341", "float_value": null, "double_value": null } } ], "timestamp_micros": "1489478204880000", "previous_timestamp_micros": "1489137436229000", "value_in_usd": null } ] }, { "user_dim": { "user_id": null, "first_open_timestamp_micros": "1488878151620000", "user_properties": [ { "key": "first_open_time", "value": { "value": { "string_value": null, "int_value": "1488880800000", "float_value": null, "double_value": null }, "set_timestamp_usec": "1488878151620000", "index": null } } ], "device_info": { "device_category": "mobile", "mobile_brand_name": null, "mobile_model_name": null, "mobile_marketing_name": null, "device_model": "507SH", "platform_version": "6.0.1", "device_id": null, "resettable_device_id": null, "user_default_language": "ru-ru", "device_time_zone_offset_seconds": "10800", "limited_ad_tracking": "false" }, "geo_info": { "continent": "Europe", "country": "Russia", "region": "Moscow", "city": "Moscow" }, "app_info": { "app_version": "1.0", "app_instance_id": "d0c587de4d5804ddc1d34f8d54b981f9", "app_store": "manual_install", "app_platform": "ANDROID", "app_id": "com.example.matsyuk.testfirebase" }, "traffic_source": null, "bundle_info": { "bundle_sequence_id": "62", "server_timestamp_offset_micros": "-499813" }, "ltv_info": null }, "event_dim": [ { "date": "20170314", "name": "select_content", "params": [ { "key": "firebase_screen_class", "value": { "string_value": "MainActivity", "int_value": null, "float_value": null, "double_value": null } }, { "key": "content_type", "value": { "string_value": "image", "int_value": null, "float_value": null, "double_value": null } }, { "key": "item_name", "value": { "string_value": "name1", "int_value": null, "float_value": null, "double_value": null } }, { "key": "firebase_event_origin", "value": { "string_value": "app", "int_value": null, "float_value": null, "double_value": null } }, { "key": "firebase_screen_id", "value": { "string_value": null, "int_value": "1109587836504693341", "float_value": null, "double_value": null } }, { "key": "item_id", "value": { "string_value": "1", "int_value": null, "float_value": null, "double_value": null } } ], "timestamp_micros": "1489478204208000", "previous_timestamp_micros": "1489137435605000", "value_in_usd": null } ] }, { "user_dim": { "user_id": null, "first_open_timestamp_micros": "1488878151620000", "user_properties": [ { "key": "first_open_time", "value": { "value": { "string_value": null, "int_value": "1488880800000", "float_value": null, "double_value": null }, "set_timestamp_usec": "1488878151620000", "index": null } } ], "device_info": { "device_category": "mobile", "mobile_brand_name": null, "mobile_model_name": null, "mobile_marketing_name": null, "device_model": "507SH", "platform_version": "6.0.1", "device_id": null, "resettable_device_id": null, "user_default_language": "ru-ru", "device_time_zone_offset_seconds": "10800", "limited_ad_tracking": "false" }, "geo_info": { "continent": "Europe", "country": "Russia", "region": "Moscow", "city": "Moscow" }, "app_info": { "app_version": "1.0", "app_instance_id": "d0c587de4d5804ddc1d34f8d54b981f9", "app_store": "manual_install", "app_platform": "ANDROID", "app_id": "com.example.matsyuk.testfirebase" }, "traffic_source": null, "bundle_info": { "bundle_sequence_id": "61", "server_timestamp_offset_micros": "-537470" }, "ltv_info": null }, "event_dim": [ { "date": "20170314", "name": "session_start", "params": [ { "key": "firebase_screen_class", "value": { "string_value": "MainActivity", "int_value": null, "float_value": null, "double_value": null } }, { "key": "firebase_event_origin", "value": { "string_value": "auto", "int_value": null, "float_value": null, "double_value": null } }, { "key": "firebase_screen_id", "value": { "string_value": null, "int_value": "1109587836504693341", "float_value": null, "double_value": null } } ], "timestamp_micros": "1489478198696000", "previous_timestamp_micros": "1489137330069000", "value_in_usd": null } ] } ]
Beauty, and only!
Now take a closer look at Queries. Choose the first ( clickable picture ):
And the following screen will open before us ( clickable image ):
Our request is rather arbitrary. Pay attention to the Results tab. Actually, in it you will see the results of your query.
If you open the Explanation tab, you will see a more detailed process of passing the request ( clickable image ):
Well, the most interesting tab is Job information ( clickable image ):
Check out Bytes Processed, Bytes Billed and Bites Tier. During the request, 26.4 KB were processed, but you pay at the lower boundary for Bites Tier = 1, that is, you pay as for 10 MB. However, judging by the documentation , 1 TB per month will be free for you, and each subsequent one will cost $ 5. It is enough for you to stop playing and try. Well, an important addition - you pay only for successful requests!
Even a very brief review on BigQuery turns out rather big. This is a very powerful and functional tool with which you can analyze data as you like. But in 5 minutes in BigQuery you will not understand exactly, unlike a regular console in GA or FA. It is therefore very cool if there is a person in your team or company who understands this and who can get any kind of results.
If you want to become this person, you can start with the introductory video from Google , which, by the way, tells about the calculation of the cost. There are also some good articles - one and two . Next, I advise you to dig in the direction of the official docks and books on BigQuery (the whole book, Karl!).
It would be great if someone has already dug well in this direction and can share tips and experiences =)
I also note that there are UI wrappers over BigQuery of the Data Studio type that allow you to load data there and conveniently visualize it. Data Studio is still in beta, but in the future it promises to be a very convenient tool.
We, in fact, continue the theme of events, as user properties are its integral part.
User properties (in Russian “User properties”) are the signs with which you can describe different segments of your user base, such as language, geographic location, etc. They are also called sticky params , as they are attached to each event.
Initially, only the default properties are attached to each event. And if in the code you call such code:
mFirebaseAnalytics.setUserProperty("license_property", mLicenseType);
then the property “license_property” will be attached to each subsequent event with a pre-set value (value “mLicenseType”). And even after restarting the application, phone, etc. this property will be attached. That is, property is also persistence .
In this case, you must pre-register your property in the console ( clickable image ):
Everything is detailed here and in api .
I note that for a particular application, you can send up to 25 properties (without taking into account the properties that are sent by default). List of properties sent by default here .
Actually in the console you can filter anything, by properies and “audience” (let's say about the “audience” below). For example, events ( pictures clickable ):
setUserProperty(...)
in GA are the setCustomDimension(...)
and setCustomMetric(...)
methods. The only thing, the dimension and metric data are not sticky and persistence, and you will need to manually attach each session to each event.
I think every application has at least two analytical tools. Usually they are much more. Analysts are also progressive people and do not stand still. But we all support it. Yes, plus traffic. So what better to do?
There is a very good Google article , which I have already mentioned, which describes various options.
Briefly introduce them so that you have an idea:
, . Android Studio , . , 15 . API? , .
FA Android Studio Assistant google-services.json
. , , , — FA.build.gradle
:
dependencies { classpath 'com.google.gms:google-services:3.0.0' // ... }
google-services
— , google-services.json
, , FA. google-services
( FA). , app/build.gradle
:
apply plugin: 'com.google.gms.google-services'
google-services.json
Firebase, , .
{ "project_info": { "project_number": "887654601522", "firebase_url": "https://fir-test3-4bab3.firebaseio.com", "project_id": "fir-test3-4bab3", "storage_bucket": "fir-test3-4bab3.appspot.com" }, "client": [ { "client_info": { "mobilesdk_app_id": "1:887654601522:android:9c6c1c11f784b956", "android_client_info": { "package_name": "com.example.matsyuk.firebasetest3" } }, "oauth_client": [ { "client_id": "887654601522-o8rolth1g5mq5qq650844chk07mib2un.apps.googleusercontent.com", "client_type": 1, "android_info": { "package_name": "com.example.matsyuk.firebasetest3", "certificate_hash": "82f13b732dec32c5ebd4498c3a7acf4bda23a846" } }, { "client_id": "887654601522-4riqkg424gb236q6mqehksn03u4hoqqg.apps.googleusercontent.com", "client_type": 3 } ], "api_key": [ { "current_key": "AIzaSyAYRPNTcgxWP7qUzI__kx9gSwxnIgc3iBo" } ], "services": { "analytics_service": { "status": 1 }, "appinvite_service": { "status": 2, "other_platform_oauth_client": [ { "client_id": "887654601522-4riqkg424gb236q6mqehksn03u4hoqqg.apps.googleusercontent.com", "client_type": 3 } ] }, "ads_service": { "status": 2 } } } ], "configuration_version": "1" }
google-services
json , your_project\app\build\generated\res\google-services\debug\values\values.xml
:
<?xml version="1.0" encoding="UTF-8"?> <resources> <string translatable="false" name="default_web_client_id">887654601522-4riqkg424gb236q6mqehksn03u4hoqqg.apps.googleusercontent.com</string> <string translatable="false" name="firebase_database_url">https://fir-test3-4bab3.firebaseio.com</string> <string translatable="false" name="gcm_defaultSenderId">887654601522</string> <string translatable="false" name="google_api_key">AIzaSyAYRPNTcgxWP7qUzI__kx9gSwxnIgc3iBo</string> <string translatable="false" name="google_app_id">1:887654601522:android:9c6c1c11f784b956</string> <string translatable="false" name="google_crash_reporting_api_key">AIzaSyAYRPNTcgxWP7qUzI__kx9gSwxnIgc3iBo</string> <string translatable="false" name="google_storage_bucket">fir-test3-4bab3.appspot.com</string> </resources>
, firebase_database_url
, google_storage_bucket
.. Firebase, .google-services.json
.
. Example applicationId
, , , com.fa.example
. flavors:
productFlavors { dev { applicationId "com.fa.example.dev" } qa { applicationId "com.fa.example.qa" } prod { // applicationId "com.fa.example" } }
FA Android Studio Assistant. Example , :
app/google-services.json
, ( flavors applicationId
) . flavor .
, google-services.json
. google-services.json
.
. Example FA. flavor . flavor . :
:
google-services.json
( ) .
. , buildTypes
, build.gradle
- :
buildTypes { release { } ultra_debug { applicationIdSuffix ".ultra_debug" } debug { applicationIdSuffix ".debug" } }
ultra_debug
debug
. , buildTypes flavors:
productFlavors { dev { applicationId "com.fa.example.dev" } qa { applicationId "com.fa.example.qa" } prod { // applicationId "com.fa.example" } }
Android Studio Assistant FA. , ?
=) :
com.fa.example.debug com.fa.example.dev.debug com.fa.example.qa.debug
«debug», . .
.
flavors. flavor (, custom
), applicationId
, flavor :
productFlavors { dev { applicationId "com.fa.example.dev" } qa { applicationId "com.fa.example.qa" } prod { // applicationId "com.fa.example" } custom { // applicationId "com.fa.example" } }
, applicationId
. ? Do the following:
com.fa.example
.google-services.json
.google-services.json
( ).google-services.json
. google-services plugin
flavor. google-services.json
, . , google-services.json
app
. .
. , google-services.json
, app/
( flavors ), , . . GA id, FA . ( SO ):
FirebaseOptions options = new FirebaseOptions.Builder() .setApplicationId("bla-bla") // Required for Analytics. .setApiKey("bla-bla") // Required for Auth. .setDatabaseUrl("bla-bla") // Required for RTDB. .build(); FirebaseApp.initializeApp(this /* Context */, options, "secondary");
«Missing google_app_id. Firebase Analytics disabled» . Firebase .google-services
- .
GA setLocalDispatcher(...)
. . , FA . GA setLocalDispatcher(-1)
, dispatchLocalHits()
. , , , ..
FA , .setAnalyticsCollectionEnabled(boolean enabled)
, . , , :
<meta-data android:name="firebase_analytics_collection_enabled" android:value="false" />
, , :
setAnalyticsCollectionEnabled(true);
. setAnalyticsCollectionEnabled(true)
. :
<meta-data android:name="firebase_analytics_collection_deactivated" android:value="true" />
FA . . , . StreamView/DebugView ( ):
StreamView, , . Snapshot ( User snapshot ), ( ):
DebugView . - . events properties, , events c properties . , DebugView .
StreamView DebugView .
GA, FA, , «», « » .. , , , = . But it is not. — , ( foreground). API FA :
setMinimumSessionDuration (long milliseconds); // default 10 sec setSessionTimeoutDuration (long milliseconds); // default 30 min
minimumSessionDuration, . foreground minimumSessionDuration, .
, sessionTimeoutDuration, . , - , ( foreground), sessionTimeoutDuration+ ( , ), .
, « , ». «» properties «country» = «Russia» «sex» = «male» event «reg_comleted» ( event) = «true».
=)
, GA.
Attribution Cohorts. , , . , .
.
. .
Pros:
Minuses:
, FA . , GA? ?
. . BigQuery. - , , — « », . , . FA + BigQuery. , .
, ! , ! !
PS , =)
Source: https://habr.com/ru/post/334292/
All Articles