At a glance: Record post-install in-app events (such as login, register, or in-app purchase) attributed to media sources and campaigns.
Why record in-app events?
In-app events provide insight into what is happening in your app and are the ideal tool to determine the value of app users and the quality of traffic originating from different media sources. Recording in-app events helps you measure KPIs such as ROI (Return on Investment) and LTV (Lifetime Value).
When users perform registrations, complete tutorials, add items to the shopping cart or make purchases, the in-app event data can record the events with the details. The implementation of in-app events is mandatory for all post-install analysis purposes.
About in-app events
An in-app event comprises an event name and can include event parameters. When you add event parameters to an in-app event, it is referred to as a in-app event. Event parameters provide you with more context and information about the occurring event. For example, while it helps to know that a user made a booking, event parameters can provide you with details such as the type of purchase, destination, and revenue.
Tip
Want to know more about in-app events? Check out this short, informative course on the AppsFlyer Learning Portal.
Predefind and custom events
In-app events that you want to send require your developer to implement code where applicable in your app. Event names and event parameters are classified as follows:
-
Predefined: These are event names and event parameters that are commonly used among different apps. We highly recommend using predefined event names and event parameters as much as possible for the following reasons:
- Predefined naming allows automatic mapping of events to partners.
- If AppsFlyer decides to change the name of any event or event parameter, your implementation is backward compatible.
- Custom: These are event names and parameters that you define for specific user scenarios that occur in your app. You can use any custom event name or parameter name string, but keep in mind that custom events need maintenance by your developer. See Tips and Limitations.
Revenue in in-app events
Event revenue
Whenever you send in-app events such as a purchase or flight
booking,
you send it with its associated revenue. The sole parameter that
carries revenue in in-app events is af_revenue
You can also record negative revenue in case a user cancels a
purchase
or if you issue a refund. To record negative revenue, all you
have
to do is append the minus sign (-) to the revenue value that
you
pass to af_revenue
af_revenue is the only parameter that accumulates your users' revenue. Always use it with in-app events that represent actual revenue generation in your business logic.
af_revenue can also have negative revenue values if you need to record events such as canceled transactions or refunds.
The revenue value must contain only numbers (and a decimal point, if required):
- Don't include any other characters or format the revenue value in any other way. This means no commas, currency signs f(or example $), special characters, or text.
- AppsFlyer provides revenue value with precision of up to five decimal places.
- The range of this value should be -1,000,000 to 1,000,000 in dollars or the equivalent original currency amount. Values outside of this range are included in raw data reports but not in aggregate reports.
- Example: 1234.56
- When revenue is sent as a string, the value inside the quotation marks must be valid. For example: "1234.56".
Note:
- AppsFlyer displays the exact revenue as sent from the SDK. It does not include any calculations for VAT or app store commissions, etc., unless these were included by the developer on the SDK side prior to it being sent to AppsFlyer.
af_currency represents the currency that is stated in af_revenue (or af_price). If af_currency is missing from the event's parameters, AppsFlyer sends it with the default value "USD".
You can use af_price as a monetary parameter that is not counted as revenue (such as in an “Add to Cart” event). This parameter refers to the individual item price. The total amount of all purchases appears under the af_revenue parameter.
Projected revenue
Advertisers use projected revenue to optimize their campaigns earlier in the user lifecycle by predicting potential user value. Projected revenue is calculated based on the user's earlier interactions and behaviors. Note: Contact AppsFlyer support to learn whether your ad network support projected revenue.
How Should Projected Revenue Be Reported to AppsFlyer?
When reporting projected revenue to AppsFlyer, it must be sent in events separate from those containing actual revenue. Advertisers should ensure that:
- Events with actual revenue and events with projected revenue are treated and reported as distinct events.
-
The projected revenue data is included in the event value,
for
example:
"event_value": { "af_projected_revenue": 0.79 }
Projected revenue in the AppsFlyer Dashboard and in reports
- Projected revenue is not included in the total revenue calculations or metrics displayed in the AppsFlyer dashboard. This ensures that the dashboard only reflects real, earned revenue.
- In raw data, projected revenue is not reported in a dedicated field but is available within the event value that contains the revenue amount sent by the advertiser.
Send projected revenue postbacks
To learn how to send projected revenue postbacks to ad networks, see Share project revenue.
Revenue currency
It's important to understand how AppsFlyer handles currency settings and currency conversion.
AppsFlyer handles the difference between app settings currency and in-app events currency using currency conversion.
The diagram above demonstrates the following process:
- In-app events are sent - different currency for each event
- AppsFlyer normalizes all currencies to USD
- AppsFlyer processes revenue data
- Revenue data in the dashboard is displayed in app settings currency
- AppsFlyer populates revenue data in raw data reports in both event and app settings currency
AppsFlyer uses Open Exchange Rates for currency conversion. The exchange rate is updated on an hourly basis. Whenever AppsFlyer performs currency conversion, it uses the exchange rate of the last hourly update.
Currency conversion
Example
In your app settings, you set currency to GBP. A user from France purchases a product using your app. The price is quoted in EUR (€). The in-app event that you send to AppsFlyer looks like this:
Map<String, Object> eventValue = new HashMap<String, Object>(); eventValue.put(AFInAppEventParameterName.REVENUE,200); eventValue.put(AFInAppEventParameterName.CONTENT_TYPE,"category_a"); eventValue.put(AFInAppEventParameterName.CONTENT_ID,"1234567"); eventValue.put(AFInAppEventParameterName.CURRENCY,"EUR"); AppsFlyerLib.getInstance().trackEvent(getApplicationContext() , AFInAppEventType.PURCHASE , eventValue);
In this case, AppsFlyer converts revenue from EUR to USD and then to GBP. Let's assume the exchange rate is €1 = $1.13. So €200 becomes $226.85. Next, AppsFlyer converts from USD to GBP. Let's assume the exchange rate is $1 = £0.78. So $226.85 becomes £176.92.
Currency display
Currency is set in the app settings. The currency that you set in the app settings, is the currency that appears in the dashboard. No matter what currency you send in-app events, the revenue in the dashboard always appears in the currency that you set in the app settings.
Example
Let's say that you send in-app events with different currencies than the one set in the app settings, or with no currency at all. In this example, currency in the app settings is set to GBP.
You send three in-app events to AppsFlyer.
- Event A has revenue of 234 and GBP as currency
- Event B has revenue of 171 and EUR as currency
- Event C has revenue of 171 but no currency specified
Revenue data in the dashboard
The revenue that appears in the dashboard is the converted value from the in-app event currency to USD and then to the app settings currency.
If no currency is specified in the event, AppsFlyer defaults to USD. The dashboard displays the event and revenue as follows:
In-Apps Events | Unique Users | Number of Actions | Revenue |
---|---|---|---|
A | 1 | 1 | £234 |
B | 1 | 1 | £149.4 - converted from EUR to USD and then to GBP. |
C | 1 | 1 | £132.9 - defaults to USD as no currency is specified. Converted from USD to GBP directly. |
Revenue data in raw data reports
If you set the currency to GBP in the app settings but send in-app events with different currencies, the raw data report shows revenue in both app settings currency and in-app event currency.
If you set the currency to GBP in the app settings but send in-app events without currency, the raw data report shows revenue in both app settings currency and in USD.
The in-app events raw data report displays the event and revenue as follows:
Event | Event Revenue | Event Revenue Currency | Event Revenue GBP |
---|---|---|---|
A | 234 | GBP | 234 |
B | 171 | EUR | 149.4 - converted from EUR to USD and then to GBP. |
C | 171 | USD | 132.9 defaults to USD as no currency is specified. Converted from USD to GBP directly. |
Sending events
There are several ways to send in-app events to AppsFlyer:
- AppsFlyer SDK: This is the most common way to send events. You can send in-app events that record user actions in the app using the AppsFlyer in-app events API at the SDK level.
- Server-to-server API: Use the server-to-server API to send events that occur outside the mobile app, directly to AppsFlyer. For example, if you have a user who is active on both web and mobile interfaces, you can record events from both sources and attribute them to the same user in AppsFlyer. It can be either an in-app event or other events, such as website events, call-center events, or purchases in your brick-and-mortar store.
- Receipt validation: This is a secure mechanism where the payment platform, for example, Apple and Google, validate that the in-app purchase took place as reported. Validating purchases is the primary tool to prevent fraudulent revenue events. It also helps you see what the real revenue is, and filters out incomplete in-app purchases.
- Hybrid apps: These apps combine native views and HTML content and can also record in-app events. However, because the SDK can only send events from the native side, developers have to forward all event data to native code.
Setting up in-app events
The process of setting up in-app events requires that the marketer and the developer work together as follows:
Step | Role | Task | Details |
---|---|---|---|
1 | Marketer | Determine the in-app events that you want to measure. Define and communicate the event names and event parameters to your developer. |
It is recommended to start with 3-5 events that you can use as KPIs to measure the quality of your users (for example, purchases, registration, and sharing). Event parameters are optional, and you can use any event parameter with any event name. See Recommended events by business vertical for typical in-app events. |
2 | Developer | Implement code in your app where applicable. | Developer documentation is here. |
3 [Optional] | Marketer | Work with your developer to set the Customer User ID field (CUID). | This field helps enrich in-app events data by cross-referencing AppsFlyer attribution data with your other data using the CUID as a key. |
4 [Optional] | Marketer | Map events to relevant partners in the dashboard. | This is an ongoing task, depending on the partners you integrate with. |
Defining an in-app event
Once you determine the in-app events that you want to measure, use our In-app event generator to define the events and parameters as follows:
- Select an event name that is most suitable to the scenario you want to record.
- Select the event parameters that you want to associate with the event. Choose parameters that will provide additional context to the event and enrich the data.
- Download the completed file from the in-app event generator, and then share it with your developer.
Example
A marketer for an eCommerce app wants to record the type of content users view in order to better understand what categories are the most popular and connect product views with product sales.
The following table shows an example of the event structure the marketer passes to the developer:
Event name | Event parameters | Parameter values | When is the event triggered? |
---|---|---|---|
af_content_view | af_price | Product price | When a user views a specific product details page |
af_content_type | Name of the product category, for example, shoes | ||
af_content_id | Product ID, for example, SKU |
Recommended events by business vertical
The following table provides links to articles that include examples and flows of the typical in-app events we suggest recording per vertical.
View in-app event data
In-app events are attributed to the media source responsible for the install throughout the lifetime of the user. Event data is presented as Life Time Value or Activity data.
You can view your in-app event data in these locations:
- Dashboard overview page: Displays real-time LTV user acquisition (UA) performance. Note: This includes revenue divided between organic and non-organic users reported via in-app events, and retargeting revenue that is double-attributed.
- Events page: Displays LTV in-app event performance across media sources
- Activity page: Displays in-app activities for the selected date range.
-
Raw data in-app event report: Displays activity data, meaning, a chronological list of the actions performed by your entire user base. This report includes event parameter values, for example:
{ "af_level":"10", "af_score":"3387", "arena":"7", "char_type":"paladin" }
Note that raw-data reporting is a premium feature.
Tips
Keep in mind the following when defining event names and parameters in the app:
- For data consistency in raw-data reporting, we recommend defining and using the same in-app event names and structures across all platforms.
- Use a minimal number of events to make it easier to compare the quality of users coming from different sources.
- It is important that you ensure the privacy of your users. Don't populate in-app event values with restricted data that can directly identify them. For example, email address, name, identity number, and in some locations postal code. For more information about restricted data, read the services privacy policy.
- Note that AppsFlyer includes the IP address of devices during engagements. In some jurisdictions or use scenarios, the IP address can be regarded as PII. We use the IP address to derive the broad geographic location (city, district level) of the device but not the specific address. If needed, you can select to mask IP addresses so that they don't appear in raw data reports.
- In-app events are the only source of revenue data in AppsFlyer. You can attach a specific revenue value to each event, and view it on your app's dashboard. Learn more about the monetizing parameters.
Limitations
Keep in mind the following when defining event names and parameters in the app:
- We recommend using only lower-case alpha-numeric characters (a-z and 0-9) for your in-app event names. Event names are case-sensitive, meaning that af_purchase and af_PURCHASE are two different events in the raw data. However, in aggregate reports (for example, Overview, or Events) they can be displayed as a single event.
- There is a cardinality limit of 300 unique events per day. Learn more
- Unique users are only counted for the first 100 events after they install the app.
- Event names cannot begin with these characters: " = + -
- Event values should not contain the + character, except in encoded URLs or encoded as per ASCII.
- Event names cannot contain empty spaces. You can use underlined spaces (low dashes) before or after the name of the event.
- Event values should not exceed 2,000 characters to avoid being shortened in raw data reports. However, if the event originates from the SDK, it is recommended to keep it under 1,000 characters to make sure that the payload is not truncated when sent in the HTTP request.
- If you include the referring URL as an event value, it must be URL encoded.
- Meta ads has some limitations regarding event names and parameters. Read about the limitations here.
FAQ
The following section includes various FAQ about in-app events.
How do I use the revenue parameter?
You can send revenue values with any parameter name and event. However, to register the revenue (including negative revenue) in the AppsFlyer raw and aggregated data, you MUST use the af_revenue parameter. Always use it with in-app events that represent actual revenue generation in your business logic.
af_currency represents the currency that is stated in af_revenue (or af_price). If af_currency is missing from the event's parameters, AppsFlyer sends it with the default value "USD".
For more information about the af_revenue parameter, see the Revenue Attribution guide.
How does AppsFlyer attribute events?
In-app events are attributed to the original media source of the app install.
Upon the install of an app (first app launch) AppsFlyer uses various attribution methods to determine the attribution of the install. At the same time, the AppsFlyer SDK creates a new unique AppsFlyer ID, which is associated with the attribution details.
Every consequent in-app event performed by the same device in the app has this ID. This enables AppsFlyer to attribute the event to the original media source. Advertisers can use this to follow the full user journey in their app.
Events of recently retargeted users may have double attribution.
AppsFlyer attributes events of attributed installs as organic when:
- More than 24 months pass after the install date
- The media source's terms dictate deleting the user-level data
- The user deletes the app's stored data on the device, forcing the creation of a new AppsFlyer ID.
Are events recorded if a device is offline?
If a user initiates an event when the internet connection is unavailable, AppsFlyer is still able to record it. This is how it works:
- SDK sends the events to the AppsFlyer servers and waits for a successful response.
- If the SDK doesn’t receive a successful response, the event is stored in the cache.
- Once the next successful response is received, the stored event is sent to the server again.
- If there are multiple events in the cache, they are sent to the server, one after the other.
Note
The SDK cache can store up to 40 events, which means that only the first 40 events that happen offline are saved. Everything that follows, until the next successful response, gets discarded.
The event time that displays in the raw data is the time the event is sent to AppsFlyer after the device goes online again. It is not the actual time that the event takes place.
What are complex in-app events and how do I set them up?
Complex in-app events enable sending multiple events in a single API call.
They are useful when you want to see several closely related user actions grouped together (for example, adding several products to the basket in a single session).
Example:
{ "af_revenue":"50.87", "af_currency":"USD", "af_receipt_id":"57601333", "product":[ { "af_content_id":"1164_8186", "af_price":"8.97", "af_quantity":"1" }, { "af_content_id":"1164_8186", "af_price":"8.97", "af_quantity":"1" }, { "af_content_id":"1164_8186", "af_price":"8.97", "af_quantity":"1" }, { "af_content_id":"1177_8185", "af_price":"8.97", "af_quantity":"1" }, { "af_content_id":"0153_9077", "af_price":"14.99", "af_quantity":"1" } ] }
Caution
Complex in-app events cause postback issues with Meta ads and Criteo. If you need the event to be fully mapped with Meta ads and Criteo, send separate events per user action (for example, send an Add to cart event per each added item). Use the in-app events raw data to group these events together.
Can I add multiple items to a single transaction?
You can add multiple items to a single transaction. Instead of single values per event parameter, you can have an array of items describing the transaction, separated by commas. The format should be a JSON string.
Example
In the same transaction, Mr. Smith purchases two identical shirts, one pair of shoes, and a hat from a US-based online store. The sequence in which each item is listed must be identical for each parameter.
"{\"af_content_id\": [\"123\",\"988\",\"399\"], \"af_quantity\": [\"2\",\"1\",\"1\"], \"af_price\": [\"25\",\"50\",\"10\"], \"af_revenue\": \"110\", \"af_currency\": \"USD\"}"
Multiple items are sent onward as an array in postbacks. Currently, Meta ads and X Ads can't parse array parameters correctly. To assist with this issue, AppsFlyer sums up the number of items (af_quantity) instead of sending it to these SRNs as an array. In our example, Meta ads would get af_quantity=4.
Note
Multiple items can be used with the following in-app events:
af_add_to_cart, af_add_to_wishlist, af_tutorial_completion, af_initiated_checkout, af_purchase, af_rate, af_spent_credits, af_content_view, af_travel_booking, af_update
How does AppsFlyer handle event deduplication?
We have an in-app event deduplication mechanism. It checks all in-app events to see if there was an identical in-app event that came from the same appsflyer_id less than 10 seconds beforehand. If such an event is found, the mechanism removes the duplicate.
Two events are considered identical if the following fields in both events are the same:
- Event name
- Event value
- App ID
- AppsFlyer ID
Note
Deduplication works only for in-app events which are sent from the SDK.
S2S in-app events don’t get deduplicated.
How long does AppsFlyer retain user-level data and what are the deletion obligations?
AppsFlyer retains user-level (raw-data) for 24 months except where otherwise directed, required, or allowed by law. Some SRNs/partners require attribution providers, including AppsFlyer, to delete SRN/partner-related user-level data before the expiry of the 24 month period.
After deletion, events related to deleted users display as organic. Past aggregate data is not changed. For more information, see Data retention and deletion obligations.
Do I need to add the OS (operating system) parameter to my events?
- The Android SDK and iOS SDK automatically add the OS (operating system) parameter.
- For the S2S API, starting July 1, 2021, you must send the OS (operating system) parameter for iOS apps. If you do not send this parameter, data is regarded as having come from an iOS 14.5 user, and this impacts the way raw data is made available.