|
| 1 | +#ifndef ANALYTICS_MOBILE_CONSOLE_MEASUREMENT_PUBLIC_ANALYTICS_H_ |
| 2 | +#define ANALYTICS_MOBILE_CONSOLE_MEASUREMENT_PUBLIC_ANALYTICS_H_ |
| 3 | + |
| 4 | +#include <cstdint> |
| 5 | +#include <optional> |
| 6 | +#include <string> |
| 7 | +#include <unordered_map> |
| 8 | +#include <variant> |
| 9 | +#include <vector> |
| 10 | + |
| 11 | +#include "c/analytics.h" |
| 12 | + |
| 13 | +namespace google::analytics { |
| 14 | + |
| 15 | +/** |
| 16 | + * The top level Firebase Analytics singleton that provides methods for logging |
| 17 | + * events and setting user properties. See <a href="http://goo.gl/gz8SLz">the |
| 18 | + * developer guides</a> for general information on using Firebase Analytics in |
| 19 | + * your apps. |
| 20 | + * |
| 21 | + * @note The Analytics SDK uses SQLite to persist events and other app-specific |
| 22 | + * data. Calling certain thread-unsafe global SQLite methods like |
| 23 | + * `sqlite3_shutdown()` can result in unexpected crashes at runtime. |
| 24 | + */ |
| 25 | +class Analytics { |
| 26 | + public: |
| 27 | + using PrimitiveValue = std::variant<int64_t, double, std::string>; |
| 28 | + using Item = std::unordered_map<std::string, PrimitiveValue>; |
| 29 | + using ItemVector = std::vector<Item>; |
| 30 | + using EventParameterValue = |
| 31 | + std::variant<int64_t, double, std::string, ItemVector>; |
| 32 | + using EventParameters = std::unordered_map<std::string, EventParameterValue>; |
| 33 | + |
| 34 | + /** |
| 35 | + * @brief Returns the singleton instance of the Analytics class. |
| 36 | + */ |
| 37 | + static Analytics& GetInstance() { |
| 38 | + static Analytics instance; |
| 39 | + return instance; |
| 40 | + } |
| 41 | + |
| 42 | + // This type is neither copyable nor movable. |
| 43 | + Analytics(const Analytics&) = delete; |
| 44 | + Analytics& operator=(const Analytics&) = delete; |
| 45 | + Analytics(Analytics&&) = delete; |
| 46 | + Analytics& operator=(Analytics&&) = delete; |
| 47 | + |
| 48 | + /** |
| 49 | + * @brief Logs an app event. |
| 50 | + * |
| 51 | + * The event can have up to 25 parameters. Events with the same name must have |
| 52 | + * the same parameters. Up to 500 event names are supported. Using predefined |
| 53 | + * events and/or parameters is recommended for optimal reporting. |
| 54 | + * |
| 55 | + * The following event names are reserved and cannot be used: |
| 56 | + * - ad_activeview |
| 57 | + * - ad_click |
| 58 | + * - ad_exposure |
| 59 | + * - ad_query |
| 60 | + * - ad_reward |
| 61 | + * - adunit_exposure |
| 62 | + * - app_clear_data |
| 63 | + * - app_exception |
| 64 | + * - app_remove |
| 65 | + * - app_store_refund |
| 66 | + * - app_store_subscription_cancel |
| 67 | + * - app_store_subscription_convert |
| 68 | + * - app_store_subscription_renew |
| 69 | + * - app_update |
| 70 | + * - app_upgrade |
| 71 | + * - dynamic_link_app_open |
| 72 | + * - dynamic_link_app_update |
| 73 | + * - dynamic_link_first_open |
| 74 | + * - error |
| 75 | + * - firebase_campaign |
| 76 | + * - first_open |
| 77 | + * - first_visit |
| 78 | + * - in_app_purchase |
| 79 | + * - notification_dismiss |
| 80 | + * - notification_foreground |
| 81 | + * - notification_open |
| 82 | + * - notification_receive |
| 83 | + * - os_update |
| 84 | + * - session_start |
| 85 | + * - session_start_with_rollout |
| 86 | + * - user_engagement |
| 87 | + * |
| 88 | + * @param[in] name The name of the event. Should contain 1 to 40 alphanumeric |
| 89 | + * characters or underscores. The name must start with an alphabetic |
| 90 | + * character. Some event names are reserved. See event_names.h for the list |
| 91 | + * of reserved event names. The "firebase_", "google_", and "ga_" prefixes are |
| 92 | + * reserved and should not be used. Note that event names are case-sensitive |
| 93 | + * and that logging two events whose names differ only in case will result in |
| 94 | + * two distinct events. To manually log screen view events, use the |
| 95 | + * `screen_view` event name. Must be UTF-8 encoded. |
| 96 | + * @param[in] parameters The map of event parameters. Passing `std::nullopt` |
| 97 | + * indicates that the event has no parameters. Parameter names can be up to 40 |
| 98 | + * characters long and must start with an alphabetic character and contain |
| 99 | + * only alphanumeric characters and underscores. Only String, Int, and Double |
| 100 | + * parameter types are supported. String parameter values can be up to 100 |
| 101 | + * characters long for standard Google Analytics properties, and up to 500 |
| 102 | + * characters long for Google Analytics 360 properties. The "firebase_", |
| 103 | + * "google_", and "ga_" prefixes are reserved and should not be used for |
| 104 | + * parameter names. String keys and values must be UTF-8 encoded. |
| 105 | + */ |
| 106 | + void LogEvent(const std::string& event_name, |
| 107 | + const std::optional<const EventParameters>& parameters) { |
| 108 | + if (!parameters.has_value()) { |
| 109 | + GoogleAnalytics_LogEvent(std::string(event_name).c_str(), nullptr); |
| 110 | + return; |
| 111 | + } |
| 112 | + GoogleAnalytics_EventParameters* map = |
| 113 | + GoogleAnalytics_EventParameters_Create(); |
| 114 | + for (const auto& [name, value] : parameters.value()) { |
| 115 | + if (auto* int_value = std::get_if<int64_t>(&value)) { |
| 116 | + GoogleAnalytics_EventParameters_InsertInt(map, name.c_str(), |
| 117 | + *int_value); |
| 118 | + } else if (auto* double_value = std::get_if<double>(&value)) { |
| 119 | + GoogleAnalytics_EventParameters_InsertDouble(map, name.c_str(), |
| 120 | + *double_value); |
| 121 | + } else if (auto* string_value = std::get_if<std::string>(&value)) { |
| 122 | + GoogleAnalytics_EventParameters_InsertString(map, name.c_str(), |
| 123 | + string_value->c_str()); |
| 124 | + } else if (auto* items = std::get_if<ItemVector>(&value)) { |
| 125 | + GoogleAnalytics_ItemVector* item_vector = |
| 126 | + GoogleAnalytics_ItemVector_Create(); |
| 127 | + for (const auto& item : *items) { |
| 128 | + GoogleAnalytics_Item* nested_item = GoogleAnalytics_Item_Create(); |
| 129 | + for (const auto& [nested_name, nested_value] : item) { |
| 130 | + if (auto* nested_int_value = std::get_if<int64_t>(&nested_value)) { |
| 131 | + GoogleAnalytics_Item_InsertInt(nested_item, nested_name.c_str(), |
| 132 | + *nested_int_value); |
| 133 | + } else if (auto* nested_double_value = |
| 134 | + std::get_if<double>(&nested_value)) { |
| 135 | + GoogleAnalytics_Item_InsertDouble( |
| 136 | + nested_item, nested_name.c_str(), *nested_double_value); |
| 137 | + } else if (auto* nested_string_value = |
| 138 | + std::get_if<std::string>(&nested_value)) { |
| 139 | + GoogleAnalytics_Item_InsertString(nested_item, |
| 140 | + nested_name.c_str(), |
| 141 | + nested_string_value->c_str()); |
| 142 | + } |
| 143 | + } |
| 144 | + GoogleAnalytics_ItemVector_InsertItem(item_vector, nested_item); |
| 145 | + } |
| 146 | + GoogleAnalytics_EventParameters_InsertItemVector(map, name.c_str(), |
| 147 | + item_vector); |
| 148 | + } |
| 149 | + } |
| 150 | + GoogleAnalytics_LogEvent(std::string(event_name).c_str(), map); |
| 151 | + } |
| 152 | + |
| 153 | + /** |
| 154 | + * @brief Sets a user property to a given value. |
| 155 | + * |
| 156 | + * Up to 25 user property names are supported. Once set, user property values |
| 157 | + * persist throughout the app lifecycle and across sessions. |
| 158 | + * |
| 159 | + * The following user property names are reserved and cannot be used: |
| 160 | + * |
| 161 | + * - first_open_time |
| 162 | + * - last_deep_link_referrer |
| 163 | + * - user_id |
| 164 | + * |
| 165 | + * @param[in] name The name of the user property to set. Should contain 1 to |
| 166 | + * 24 alphanumeric characters or underscores, and must start with an |
| 167 | + * alphabetic character. The "firebase_", "google_", and "ga_" prefixes are |
| 168 | + * reserved and should not be used for user property names. Must be UTF-8 |
| 169 | + * encoded. |
| 170 | + * @param[in] value The value of the user property. Values can be up to 36 |
| 171 | + * characters long. Setting the value to `std::nullopt` removes the user |
| 172 | + * property. Must be UTF-8 encoded. |
| 173 | + */ |
| 174 | + void SetUserProperty(const std::string& name, |
| 175 | + std::optional<std::string> value) { |
| 176 | + const char* value_ptr = value.has_value() ? value->c_str() : nullptr; |
| 177 | + GoogleAnalytics_SetUserProperty(name.c_str(), value_ptr); |
| 178 | + } |
| 179 | + |
| 180 | + /** |
| 181 | + * @brief Sets the user ID property. |
| 182 | + * |
| 183 | + * This feature must be used in accordance with |
| 184 | + * <a href="https://www.google.com/policies/privacy">Google's Privacy |
| 185 | + * Policy</a> |
| 186 | + * |
| 187 | + * @param[in] user_id The user ID associated with the user of this app on this |
| 188 | + * device. The user ID must be non-empty and no more than 256 characters |
| 189 | + * long, and UTF-8 encoded. Setting user_id to std::nullopt removes the |
| 190 | + * user ID. |
| 191 | + */ |
| 192 | + void SetUserId(std::optional<std::string> user_id) { |
| 193 | + if (!user_id.has_value()) { |
| 194 | + GoogleAnalytics_SetUserId(nullptr); |
| 195 | + } else { |
| 196 | + GoogleAnalytics_SetUserId(user_id->c_str()); |
| 197 | + } |
| 198 | + } |
| 199 | + |
| 200 | + /** |
| 201 | + * @brief Clears all analytics data for this instance from the device and |
| 202 | + * resets the app instance ID. |
| 203 | + */ |
| 204 | + void ResetAnalyticsData() { GoogleAnalytics_ResetAnalyticsData(); } |
| 205 | + |
| 206 | + /** |
| 207 | + * @brief Sets whether analytics collection is enabled for this app on this |
| 208 | + * device. |
| 209 | + * |
| 210 | + * This setting is persisted across app sessions. By default it is enabled. |
| 211 | + * |
| 212 | + * @param[in] enabled A flag that enables or disables Analytics collection. |
| 213 | + */ |
| 214 | + void SetAnalyticsCollectionEnabled(bool enabled) { |
| 215 | + GoogleAnalytics_SetAnalyticsCollectionEnabled(enabled); |
| 216 | + } |
| 217 | + |
| 218 | + private: |
| 219 | + Analytics() = default; |
| 220 | +}; |
| 221 | + |
| 222 | +} // namespace google::analytics |
| 223 | + |
| 224 | +#endif // ANALYTICS_MOBILE_CONSOLE_MEASUREMENT_PUBLIC_ANALYTICS_H_ |
0 commit comments