Introduction Last updated: 28-08-2022

Learn how to use AppNava to allow everyone in your organization to get the business data they need without bothering technical teams.

What is Appnava?

Nava was founded back in 2019 to make apps and games richer and happier. We are a team of four awesome tech and mobile data experts who aspire to bring a revolution to the mobile and digital world. Data-driven solutions and machine learning utilization just run in our blood! This team of four excels at modelling complex user behaviours for mobile apps and predicting the future of your customers. With our experience in data science and engineering, we are putting forth our best to make you thrive. After a year of model development, we are happy to be there for mobile apps and games with data driven insights.

What makes Appnava different?

Know Your Players

Understand and analyze the what, when and why of your players' behaviour. Understand the past; what happened and why! At this stage, machine learning algorithms start being trained.

Predict Next Behaviour

Start predicting how your players will behave in the future even they don't know yet. Our registered machine learning algorithms predict player behavior. Nava allows you to understand your players much more deeper.

Take Right Actions

Everyone is different in many ways; tastes, lifestyles, expectations… Showing the same offer to everybody does not make sense. Personalize your campaign and game regarding this knowledge.

How Appnava Works?

Connect to the largest mobile ecosystem with integrated partners globally. Just select your analytics partners and measurement tools (Google Analytics, Game Analytics, etc.). Then, on the receiving side, choose the API that works for you to get access to your data, all of the time. With completed API connection, the mapping system is working to choose the required features/variables from your raw data. Here 80% match is enough to continue to the next steps.

For next steps you can go to this How to Nava page to learn more!

APIs

When you use an application on your mobile phone, the application connects to the Internet and sends data to a server. The server then retrieves that data, interprets it, performs the necessary actions and sends it back to your phone. The application then interprets that data and presents you with the information you wanted in a readable way. This is what an API is - all of this happens via API. You can learn about what APIs we are using in this section.

Integration

Start predicting the future behavior of new players while even they do not know how to behave in the future. Nava defines player groups who are likely to complete a specific action and conversion events. So you can engage with players before they churn; attract players who are likely to complete in-app purchases and much more. Also with Nava, you can choose the right balance between segment size and accuracy.

Unity Code Implementation

  • This is a numerator, because we really need to wait Firebase's Dependency check (and init).
  •                             
      using System;
      using System.Collections;
      using System.Text;
      using System.Threading.Tasks;
      using Firebase;
      using Firebase.Extensions;using Firebase.RemoteConfig;
      using UnityEngine;
      using UnityEngine.Networking;
    
      public class AppNava : MonoBehaviour
    	private bool _checkUserConversion            = true;  // Whether user conversion event should be fired.
    	private bool _checkUserValuation             = true;  // Whether user valuation should be requested from AppNava.
    	private bool _shouldCheckUserValuationFaster = false; // Whether user valuation should be requested from AppNava, earlier. This will be true if this is not the user's first gameplay.
    
    	private const int CONVERSION_SECONDS          = 450; // Send conversion event after.
    	private const int QUICK_CONVERSION_SECONDS    = 300; // We will use this if this is not the user's first session and if we need the user valuation.
    	private const int APPNAVA_CHECK_SECONDS       = 550; // Request the user valuation from AppNava after.
    	private const int QUICK_APPNAVA_CHECK_SECONDS = 400; // We will use this if this is not the user's first session and if we need the user valuation.
    	private const int TRY_AGAIN_SECONDS           = 90;  // The time, in case of an error, to re-request the user valuation from AppNava.
    
    	public string UserAnalyticsId = null; // User Firebase Analytics ID.
    
    	private IEnumerator Start()
    	{
    		//	Wait for Firebase init.
    		var task = FirebaseApp.CheckAndFixDependenciesAsync();
    		while(!task.IsCompleted)
    			yield return null;
    
    		//	Get Firebase Analytics ID
    		StartCoroutine(GetAndSetID());
    
    		_checkUserValuation  = !PlayerPrefs.HasKey("userValuated");
    		_checkUserConversion = !PlayerPrefs.HasKey("userHasConversion");
    
    		if(PlayerPrefs.GetInt("AppOpenCount") > 0) // Check user app open count, and if this is not the first open and user has no valuation yet, prepare boolean properties.
    		{
    			if(_checkUserValuation)
    				_shouldCheckUserValuationFaster = true;
    
    			// We need to set these to false to quickly exit from the LateUpdate.
    			_checkUserValuation  = false;
    			_checkUserConversion = false;
    		}
    	}
    
    	private void LateUpdate()
    	{
    		// This won't work in the Unity Editor
    		// #if UNITY_EDITOR
    		// 			return;
    		// #endif
    
    		if(UserAnalyticsId is null)
    			return;
    
    		if(_checkUserConversion && Time.realtimeSinceStartup > CONVERSION_SECONDS)
    			SendXMinutesConversion();
    
    		if(!_checkUserConversion && _checkUserValuation && Time.realtimeSinceStartup > APPNAVA_CHECK_SECONDS)
    			RequestUserValuation();
    	}
                            
  • Starts a Task to get the Firebase Analytics ID of the user and sets the UserAnalyticsId. Also, if _shouldCheckUserValuationFaster is true, then it automatically fires user valuation request.
  •  
    	private IEnumerator GetAndSetID()
    	{
    		var task = Firebase.Analytics.FirebaseAnalytics.GetAnalyticsInstanceIdAsync();
    
    		while(!task.IsCompleted)
    			yield return null;
    
    		if(!task.IsFaulted)
    		{
    			UserAnalyticsId = task.Result; // Set Firebase Analytics ID
    
    			if(_shouldCheckUserValuationFaster)
    				RequestUserValuation(QUICK_APPNAVA_CHECK_SECONDS, true);
    		}
    		else
    		{
    			Debug.LogError("ID Task Failed for Firebase Analytics");
    		}
    	}
         
  • Starts the _RequestAPI numerator and sets _checkUserValuation to false.
  •  
    	/// <param name="after">Send request after (seconds)</param>
    	/// <param name="sendConversion">For a delayed (after>0) request, if the conversion event should be sent?</param>
    	private void RequestUserValuation(float after = 0f, bool sendConversion = false)
    	{
    		StartCoroutine(_RequestAPI(after, sendConversion));
    		_checkUserValuation = false;
    	}
         
  • Handles the web request to the API of AppNava.
  •  
    	/// <param name="after">Send request after (seconds)</param>
    	/// <param name="sendConversion">For a delayed (after>0) request, if the conversion event should be sent?</param>
    	/// <returns></returns>
    	private IEnumerator _RequestAPI(float after = 0f, bool sendConversion = false)
    	{
    		if(UserAnalyticsId == null)
    			yield break;
    
    		if(after > 0f)
    		{
    			var passedTime = 0f;
    
    			while(passedTime < after)
    			{
    				passedTime += Time.deltaTime;
    
    				if(sendConversion && passedTime > QUICK_CONVERSION_SECONDS)
    				{
    					sendConversion = false;
    					SendXMinutesConversion();
    				}
    
    				yield return null;
    			}
    		}
    
    		var jsonData = "{\"user_pseudo_id\": \""+ UserAnalyticsId + "\"}"; // User's Firebase identifier.
    		var dataRaw  = Encoding.UTF8.GetBytes(jsonData);
    		var www      = UnityWebRequest.Post("https://appnavauservaluationlinkgoeshere.com", jsonData);
    
    		www.uploadHandler   = new UploadHandlerRaw(dataRaw);
    		www.downloadHandler = new DownloadHandlerBuffer();
    		www.SetRequestHeader("Content-Type", "application/json");
    		www.SetRequestHeader("x-api-key", "appnavaapikeygoeshere");
    		www.SetRequestHeader("Accept", "application / json");
    
    		yield return www.SendWebRequest();
    
    		if(www.result != UnityWebRequest.Result.Success)
    		{
    			Debug.LogError(www.error);
    			yield return new WaitForSeconds(TRY_AGAIN_SECONDS);
    			//Try Again
    			StartCoroutine(_RequestAPI());
    		}
    		else
    		{
    			var result = (AppNavaResponse) JsonUtility.FromJson(www.downloadHandler.text, typeof(AppNavaResponse)); // Parse JSON response text to the AppNavaResponse struct.
    
    			if(result.requestResult == 1) // AppNava sends the requestResult as "0" if the valuation is failed.
    			{
    				// SUCCESS!
    
    				// This is optional: Set user property in Firebase (we will use this to segment the user for Firebase Remote Config).
    				SetUserValuationProperty(result.predictionResultMessage);
    
    				PlayerPrefs.SetInt("userValuated", 1);
    				PlayerPrefs.Save();
    			}
    			else
    			{
    				Debug.LogError("User has no valuation yet!");
    				yield return new WaitForSeconds(TRY_AGAIN_SECONDS);
    				//Try Again
    				StartCoroutine(_RequestAPI());
    			}
    		}
    	}
         
  • Send the user conversion event (passed_x_minute) to send all cached events to Firebase Analytics.
  •  
    	private void SendXMinutesConversion()
    	{
    		// Sent conversion event for the user
    		Firebase.Analytics.FirebaseAnalytics.LogEvent("passed_x_minutes");
    
    		_checkUserConversion = false;
    
    		PlayerPrefs.SetInt("userHasConversion", 1);
    		PlayerPrefs.Save();
    	}
         
  • Sets the user's Firebase UserValueGroup property.
  •  
    	/// <param name="userType">User Type From AppNava</param>
    	private void SetUserValuationProperty(string userType)
    	{
    		Firebase.Analytics.FirebaseAnalytics.SetUserProperty("UserValueGroup", userType);
    
    		// This is optional: Get remote config (ad settings, level settings, etc) for this user.
    		StartCoroutine(UpdateValuatedUserRemoteConfig());
    	}
         
  • Delayed Firebase Remote Config Fetch.
  •  
    	/// <returns></returns>
    	private IEnumerator UpdateValuatedUserRemoteConfig()
    	{
    		var passed = 0f;
    		while(passed < 5f) // Just wait for a while for Firebase to update user property (usually 5 seconds is enough for this).
    		{
    			passed += Time.deltaTime;
    			yield return null;
    		}
    
    		FetchRemoteConfigDataAsync();
    	}
         
  • Update Firebase Remote Config
  •  
    	private void FetchRemoteConfigDataAsync()
    	{
    		Task fetchTask = FirebaseRemoteConfig.DefaultInstance.FetchAsync(TimeSpan.Zero);
    		fetchTask.ContinueWithOnMainThread(FetchCompleteMethod);
    	}
     
  • Firebase Remote Config Task Handler
  •  
    	/// <param name="firebaseRemoteTask">Firebase Remote Config Task</param>
    	private void FetchCompleteMethod(Task firebaseRemoteTask)
    	{
    		// Update Firebase Remote Config related variables.
    	}
    
    	public struct AppNavaResponse
    	{
    		// Sample response: {"requestResult": 1, "requestResultMessage": "Prediction succeeded.", "predictionResultMessage": "g_0"}
    		public int    requestResult;
    		public string requestResultMessage;
    		public string predictionResultMessage;
    	}
         }

    Database

    In this section you can learn about how to configure database connection. Below steps describe how Nava works for Firebase / Google Cloud & Unity customers

    GCP

    Collect Data

    Allow us to pull your data

    • Select the project 1
    • Select the analytics data set 2
    • Click SHARE DATASET 3
    • Type [email protected] as new member 4
    • Select roles Viewer and BigQuery Data Viewer and click Add button 5
    • Click Done button 6
    • Repeat above steps for [email protected].
      • Type [email protected] as new member 4
      • Select roles Viewer and BigQuery Data Viewer and click Add button 5
      • Click Done button 6

    Add a product on your Nava account

    • Go to Products tab on Company page
    • Click Add Product button
    • Type your BigQuery Dataset ID as shown near 7 (It is all lowercase and uses hyphens instead of spaces)
    • Fill the rest of the form and save your product

    Trigger Model Training Jobs

  • Go to your Product page
    • Click Push Data & Choose Models button
    • Check the models you want to use (For more information about models, check Guides > Prediction Models page)
    • Write a tag for the dataset
    • When you click the Done button, a record for each model you selected will be inserted to Data Preparation section
    • We will be notified and start working on your models
    • When your models are ready, you will be notified by e-mail

    Note

    Usually a dataset of 1.000.000 events and 30.000 distinct users is needed for the models to be working. We will find the time-point after which these numbers are met and update the associated columns..

    Use Predictions

  • You will be able to see the ready-to-use models in Trained Models section
    • Go to Firebase Console and define a User Property
    • Embed shown sample code 8 in your Unity scripts which sets the user property value depending on the prediction
    • Go to Google Cloud Console and create a new Cloud Function with the shown sample code 9
    • Use Firebase Remote Config for taking actions according to predictions

    Note

    You need to define a conversion event and log it right before calling the Google Cloud Function so not-yet-collected events will be flushed to BigQuery and then they can be used for prediction.

    AWS

    Below steps describe how Nava works for AWS customers

    Collect Data

    Allow us to pull your data

    • Go to AWS S3 Buckets
    • Click the bucket you use for event data collection
    • Select Permissions tab
    • Scroll down to Bucket Policy section and click Edit.
    • Enter the Bucket Policy.
    • Bucket Policy
       {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Sid": "AppNavaDataPullPolicy",
                  "Effect": "Allow",
                  "Principal": {
                      "AWS": "arn:aws:iam::741323546032:root"
                  },
                  "Action": [
                      "s3:ListBucket",
                      "s3:GetObject"
                  "Resource": [
                      "arn:aws:s3:::&lt;your-bucket-name-here&gt;/*",
                      "arn:aws:s3:::&lt;your-bucket-name-here&gt;"
                  ]
              }
           ]
    • Click Save 4

    Add a product on your Nava account

    • Go to Products tab on Company page
    • Click Add Product button
    • Select Amazon Web Services as Data Location
    • Type your S3 bucket name
    • Fill the rest of the form and save your product

    Trigger Model Training Jobs

  • Go to your Product page
    • Click Push Data & Choose Models button
    • Check the models you want to use (For more information about models, check Guides > Prediction Models page)
    • Write a tag for the dataset
    • When you click the Done button, a record for each model you selected will be inserted to Data Preparation section
    • We will be notified and start working on your models
    • When your models are ready, you will be notified by e-mail

    Note

    Usually a dataset of 1.000.000 events and 30.000 distinct users is needed for the models to be working. We will find the time-point after which these numbers are met and update the associated columns.

    Use Predictions

  • You will be able to see the ready-to-use models in Trained Models section
    • Post data to the given endpoint
    • Prediction will be returned in JSON format
    • Take your actions according to predictions

    Dashboard

    Introducing dashboard and information about user interfaces

    What is a Dashboard?

    A dashboard is a visual display of all of your data. While it can be used in all kinds of different ways, its primary intention is to provide information at-a-glance.

    A dashboard usually sits on its own page and receives information from a linked database. In many cases it’s configurable, allowing you the ability to choose which data you want to see and whether you want to include charts or graphs to visualize the numbers..

    Why Are Dashboards Important?

    Dashboards allow all kinds of professionals the ability to monitor performance, create reports and set estimates and targets for future work.

    Other benefits include:

    • A visual representation of performance, such as with charts and graphs
    • The ability to identify trends
    • An easy way of measuring efficiency
    • The means to generate detailed reports with a single click
    • The capacity to make more informed decisions
    • Total visibility of all systems, campaigns, and actions
    • Quick identification of data outliers and correlations

    Resources

    In this section you can learn about what are our resources and how to use them

    ROI and ROAS Calculator

    ROI definition

    ROI stands for “Return on Investment.” Essentially, it’s a measurement of the return on a particular investment, relative to the cost of the investment. In other words, it’s a ratio between your net profit and investment. There’s a simple formula that you can use to work out the ROI: ROI = (Net Profit / Net Spend) x 100

    ROAS definition

    ROAS stands for “Return on Ad Spend.” ROAS can help you determine the efficiency of your online advertising campaigns by calculating the amount of money your business earns for each pound it spends on advertising. You can use the following formula to calculate ROAS: ROAS = (Revenue Generated from Ads / Advertising Spend) x 100.

    The difference between ROI and ROAS

    When it comes to ROI vs. ROAS, there are a couple of major differences. Firstly, ROAS looks at revenue, rather than profit. Secondly, ROAS only considers direct spend, rather than other costs associated with your online campaign. In a nutshell, ROAS is the best metric to look at for determining whether your ads are effective at generating clicks, impressions, and revenue. However, unlike ROI, it won’t tell you whether your paid advertising effort is actually profitable for the company.

    Should I use ROI or ROAS?

    When you consider ROI vs. ROAS, it’s important to remember that it isn’t an either/or situation. Whereas ROI can help you understand long-term profitability, ROAS may be more suited to optimising short-term strategy. To craft an effective digital marketing campaign, you’ll need to utilise both the ROI and ROAS formulas. ROI provides you with insight into the overall profitability of your advertising campaign, while ROAS can be used to identify specific strategies that can help you improve your online marketing efforts and generate clicks and revenue.

    Tip

    AppNava helps you automate payment collection, cutting down on the amount of admin your team needs to deal with when chasing invoices. You can go this page and try our ROI and Roas Calculator!

    Do you want to know about the titles of the fields you need to enter into the calculator?

    Read below for more info!

    LTV

    LTV is lifetime value. This is the estimated value that you expect to extract from the player. It makes more sense to couple this lifetime value with a number of days during which the user interacts with the product (the game in this case). This enables us to study whether we are on the right track, and to reason about the product. So, LTV365 is the expected (read average) value or revenue we get from a player after 365 days or 1 year after coming into contact with the game for the first time.

    Retention

    Retention is a measure that will tell us how the players will keep interacting with the game. Day 1 retention (D1), is a percentage of how many players returned to the game after launching it for the first time (D0). The higher the retention, the better because it means that players keep coming back, so there is something about the product/game/app that motivated them to return.

    ARPDAU

    ARPDAU is average revenue per daily active user. This metric is very convoluted. By itself, it doesn’t say much. An ARPDAU of 2€ says very little. If you have a restaurant and DAU (daily active user), is the number of customers that walk in, 2€ ARPDAU might leave you bankrupt. For a mobile game, if you create a compelling title where on average you get 2€ per daily active user then you might have struck gold.

    CPI

    CPI is the cost per install. Lately, User Acquisition (UA), is an integral part of the business model of scaling F2P mobile games. And with more and more publishers paying to acquire users, the market is getting more and more competitive, and the cost per install and acquiring a new player is going through the roof.

    UA

    So User Acquisition works just like the old fashioned advertisements. You pay upfront, to get customers/players/users walking in, and hopefully, those that convert (end up buying something), will make up for the price of the advertisement and yield some extra revenue. So it’s an upfront investment and in order to minimize the risks associated with this investment, we have to study and predict how we will make the money back with a profit.