Upsight logo Back to top

Android

Overview


Upsight, formerly PlayHaven, is the most comprehensive analytics and marketing platform for web and mobile apps. We are building a business engine to help our customers better understand user behavior, decide what it means, and act to impact key goals.

If you have any questions, visit the Publish Guide or contact Upsight Support. We also recommend reviewing our Optimization Guides to learn the best practices and get the most out of your Upsight integration.

The Upsight Android SDK currently supports Android API Level 10 and higher.

Getting Started

Prerequisites


Token and Secret

Every app on the Upsight Marketing Dashboard has a unique Token and a unique Secret to identify it. These are both alphanumeric strings 32 characters long. The token and secret uniquely identify your application and prevent others from making API requests on your behalf. They are located on the Upsight Dashboard in the App Settings page for your application.

Note Both the Token and the Secret will be required in order to connect your app to the Dashboard.

You may choose to pass these into Upsight as resources by adding them to res/values/strings.xml.

Note If you are using Maven, the path would be src/main/android/res/values/strings.xml.

<string name="token">fedbca9876543210fedbca9876543210</string>
<string name="secret">fedbca98765432100123456789abcedf</string>

Placement Tags

Placements are hooks within your app that can trigger Upsight content such as cross-promotions for your other apps or announcements. To create a Placement in your app you will need a Placement Tag to identify the Placement on the Dashboard. To create a Placement Tag, you will need access to the Upsight Dashboard.

It is recommended that you add as many varied placements as possible to give you the most flexibility to experiment and connect with your users throughout the app experience. These placements will remain invisible to your players until content is assigned to them via the Upsight Marketing Dashboard.

In this example, you will create a Placement that can associate with your app launching.

  1. Click on your app on the Upsight Marketing Dashboard homepage.
  2. Click on the App Settings button.
  3. Click on the Placements link.
  4. Click on the Add Placement button.
  5. In the Placement Tag field, enter app_launch.
  6. In the Description field, enter a relevant description.
  7. Click the Save button.

The Add Placement Screen

For more information on Placements, refer to the Placements Guide for best practices and tips.

Content Units

Although your app can be integrated without any Content Units, you can only full experience and test an integration by having a Content Unit that is linked to a Placement on the Upsight Marketing Dashboard. This will allow you to see what your users will see when a Placement is triggered in your app.

In this example, you will create an Internal Cross-Promotion and associate it to your app_launch placement.

  1. Click on your app on the Upsight Marketing Dashboard homepage.
  2. Click on the Add Content button.
  3. Click on on the Add Internal Cross-Promotion button.
  4. Enter Test Ad for the Internal Cross-Promotion name.
  5. Enter name of app(s) for Internal Cross-Promotion.
  6. Upload image(s) associated with Internal Cross-Promotion.
  7. Under Placement(s), check the box for app_launch placement you created.
  8. Click the Publish button.

Add an Internal Cross-Promotion Screen

Getting Started

Step 1 Add Upsight SDK to the Project


The Upsight SDK is distributed as an Android Library Project, or APKLIB. Unlike a library distributed as a JAR, an APKLIB allows you as an app developer to use Android resources (such as images and strings) from your SDK.

For access to Upsight's Marking SDK, please contact your Customer Success Manager.

Getting Started

Step 2 Make an Open Call


Making an Open Call is required as it assists in collecting accurate data to measure performance and effectiveness of your implementations.

We will require the Token and Secret that we defined in XML earlier on. We can reference them in our Java code to configure the PlayHaven object.

PlayHaven.configure(this, R.string.token, R.string.secret);

Once PlayHaven has been configured, we can create an Open request and send it.

OpenRequest open = new OpenRequest();
open.send(this);

We recommend you place this in the method that initializes your activity like the onCreate(Bundle) method.

Important If you are using the Enterprise and regular SDKs, make sure to call the startSession method before making an OpenRequest Open Call.

Getting Started

Step 3 Requesting Content Units


You will need to incorporate content request calls into your application to display content units that are defined in the Upsight dashboard. Content requests are made using your application token, secret, and a placement tag to identify the placement for which you are requesting content.

The example below demonstrates a content request for the placement app_launch. In the example, we'll use the SDK's convenience method to create the appropriate intent. The first parameter is our Content (i.e. this Activity). The second paramter is our placement tag as defined in the Dashboard.

startActivity(FullScreen.createIntent(this, "app_launch"));

Once the ad is closed, the activity passed as this will be resumed.

You can also set additional options or disable the loading overlay, you can view these instructions in the advanced section here.

Getting Started

Step 4 Integration Checklist


To help make the integration process easier, we've created a checklist with troubleshooting tips that you can follow. If you are not getting expected results after integration, consults the checklist to see if there are any steps that you are missing.

Integration Checklist

Content Unit Types

Anouncements


Announcements are messages delivered to players in your app. Use the Upsight Dashboard to set up an announcement. No additional code is required.

Content Unit Types

Internal Cross-Promotions


Internal Cross-Promotions are customizable promotions for your own apps. See Help Center overview for more information. No additional code is required.

Content Unit Types

More Games Widget


Upsight’s More Games Widget displays specific apps that you decide to promote. Use the Upsight Dashboard to determine what apps are being displayed in your More Games Widget.

The More Games button is a standard Android button so you can specify it in XML or in Java. The following is an example specifying the button with XML.

<com.playhaven.android.view.MoreGames
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawablePadding="2sp"
    android:id="@+id/more"
    android:text="@string/moregames.text"
    android:onClick="moreGamesClicked"
    playhaven:placementTag="@string/moregamesexample.tag"
    playhaven:badgeTextColor="@color/cornsilk"
    />

In the example we specify values for the playhaven:placementTag and playhaven:badgeTextColor properties. The former is for specifying the placement tag we defined on the Upsight Dashboard, and the latter is the color for the number on the badge.

Next we will implement the RequestListener.

implements RequestListener
...
@Override
public void handleResponse(Context context, String json) {
}

@Override
public void handleResponse(Context context, PlayHavenException e) {
}

And add it to our Open request.

OpenRequest open = new OpenRequest();
open.setResponseHandler(this);
open.send(this);

Then, we will want to implement the handleResponse method to update the More Games badge. We do it this way because the Open request must be complete before making this request.

/**
 * Now that the Open is complete, tell the Badge to update
 */
 ((MoreGames) findViewById(R.id.more)).load(this);

Finally, we implement a moreGamesClicked method. This is really just a startActivity method moved into our new method.

/**
 * Now we start the new Activity.
 * Once the ad is closed, this Activity will be resumed.
 */
 startActivity(FullScreen.createIntent(this, getResources().getString(R.string.moregames_tag)));

Content Unit Types

Opt-In Data Collection


Opt-In Data Collection is an in-app promotion that gives players the option to provide you with valuable information like their email address, name, or age. Use the Upsight Dashboard to display an Opt-In Data Collection Content Unit in the same way that other Content Units are displayed. No additional code is required.

Content Unit Types

Rewards


Rewards are items you define that are given to your users using the Upsight infrastructure. Any content unit can contain a reward for your user. See Help Center overview for more information.

To add a reward to your application, you must:

  • replace the startActivity call with a startActivityForResult call.
  • have a content request that uses a placement that will give you a reward content unit from your Upsight dashboard.
  • add logic to the onActivityResult method to handle any Rewards messages that arrive.

For more information on using the startActivityForResult call and the onActivityResult method, please see the Content Result section.

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data){
  if(requestCode != EXAMPLE_REWARD_REQUEST_CODE) return;

  Bundle adData = data.getBundleExtra(PlayHavenView.BUNDLE_DATA);
  if(adData == null) return;

  for(Reward reward : adData.<Reward>getParcelableArrayList(PlayHavenView.BUNDLE_DATA_REWARD))
    Log.d(TAG, "Reward Collected:  " + reward);
}

In this example we:

  • Check if the request code matches the unique ID we assigned to Rewards and exit if it does not match.
  • Grab the BUNDLE_DATA from the Intent using the getBundleExtra method.
  • Check if the Bundle Data exists and exit if it does not.
  • Extract any granted BUNDLE_DATA_REWARD objects from the Bundle Data.
  • Log the reward.

This line returns an ArrayList<Parcelable> from the adData Bundle (using the BUNDLE_DATA_REWARD key) and casts it to an ArrayList<Reward>:

  for(Reward reward : adData.<Reward>getParcelableArrayList(PlayHavenView.BUNDLE_DATA_REWARD))

If you want to avoid using Generics you could, alternatively, do:

for(Parcelable parcel : adData.getParcelableArrayList(PlayHavenView.BUNDLE_DATA_PURCHASE))
{
    Purchase purchase = (Purchase) parcel;
    Log.d(TAG, "Purchase: (" + purchase.getSKU() +") " + purchase.getTitle());
}

Similarly, you could change the logs to be more explicit by printing the quantity and tag.

Log.d(TAG, String.format("Reward Collected: %d %s\n", reward.getQuantity().intValue(), reward.getTag() ));

Content Unit Types

Virtual Goods Promotion


A Virtual Goods Promotion (VGP) is a full-display promotion used to increase in-app purchases.

If the Upsight servers are made aware that a given user has already purchased a non-consumable In-App Purchase item, it will not show Virtual Goods Promotion Content Units for that item to that user. This is to avoid showing the user a promotion for an item that they have already purchased.

To add a purchase to your application, you must:

  • replace the startActivity call with a startActivityForResult call.
  • have a content request that uses a placement that will give you a VGP content unit from your Upsight dashboard.
  • add logic to the onActivityResult method to handle any VGP messages that arrive.

For more information on using the startActivityForResult call and the onActivityResult method, please see the Content Result section.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if(requestCode != EXAMPLE_VGP_REQUEST_CODE)
    return;

  PlayHavenView.DismissType dismissType = (PlayHavenView.DismissType) data.getSerializableExtra(PlayHavenView.BUNDLE_DISMISS_TYPE);
  if(dismissType != PlayHavenView.DismissType.Purchase) return;

  Bundle adData = data.getBundleExtra(PlayHavenView.BUNDLE_DATA);
  if(adData == null) return;

  for(Purchase purchase : adData.<Purchase>getParcelableArrayList(PlayHavenView.BUNDLE_DATA_PURCHASE))
    Log.d(TAG, "Purchase: (" + purchase.getSKU() +") " + purchase.getTitle());
}

In this example we:

  • Check if the request code matches the unique ID we assigned to Virtual Goods Promotion and exit if it does not match.
  • Grab the BUNDLE_DISMISS_TYPE from the Intent using the getSerializableExtra method.
  • Check if the Dismiss Type is a Purchase and exit if it does not.
  • Grab the BUNDLE_DATA from the Intent using the getBundleExtra method.
  • Check if the Bundle Data exists and exit if it does not.
  • Extract any granted BUNDLE_DATA_PURCHASE objects from the Bundle Data.
  • Log the purchases's SKU and title.

This line returns an ArrayList<Parcelable> from the adData Bundle (using the BUNDLE_DATA_PURCHASE key) and casts it to an ArrayList<Purchase>:

for(Purchase purchase : adData.<Purchase>getParcelableArrayList(PlayHavenView.BUNDLE_DATA_PURCHASE))

If you want to avoid using Generics you could, alternatively, do:

for(Parcelable parcel : adData.getParcelableArrayList(PlayHavenView.BUNDLE_DATA_PURCHASE))
{
  Purchase purchase = (Purchase) parcel;
  Log.d(TAG, "Purchase: (" + purchase.getSKU() +") " + purchase.getTitle());
}

Advanced

Content Display Options


By default, the SDK shows a brief loading screen before displaying content. FullScreen content units can take a third parameter that controls the display of the loading overlay in the SDK.

Example:

This content request will show the placement attached to "content_example" with no loading screen:

startActivity(FullScreen.createIntent(this, "content_example", PlayHavenView.NO_DISPLAY_OPTIONS));

Settings:

NO_DISPLAY_OPTIONS

If you specify NO_DISPLAY_OPTIONS, no additional indicators will be added.

DISPLAY_OVERLAY

If you specify DISPLAY_OVERLAY only, a partially transparent overlay will be added until the content is ready to be displayed.

enter image description here

DISPLAY_ANIMATION

If you specify DISPLAY_ANIMATION only, an indeterminate progress indicator will be shown until the content is ready to be displayed.

enter image description here

DISPLAY_OVERLAY | DISPLAY_ANIMATION

If you “or” the DISPLAY_OVERLAY and DISPLAY_ANIMATION flags together, both the overlay and progress indicator will be displayed.

enter image description here

AUTO_DISPLAY_OPTIONS

If you specify AUTO_DISPLAY_OPTIONS, the system will intelligently determine what is best for viewing.

Advanced

Content Result


Making a Content Request with the startActivityForResult method instead of the startActivity method allows you to send a unique ID that you can check for in the onActivityResult callback. This allows you to use the same method for multiple requests. The id you choose is arbitrary as long as it is unique.

private static final int EXAMPLE_REWARD_ID = 10001;
private static final int EXAMPLE_IAP_ID = 10002;

As a reminder, this is what a regular startActivity method looks like.

startActivity(Intent)

To send the unique ID, we replace it with the startActivityForResult method.

startActivityForResult(Intent, Unique_ID)

So, our request will now look like this.

startActivityForResult(FullScreen.createIntent(this, "placement_tag"), EXAMPLE_REWARD_ID);

Now that we will get a callback, we can implement it. Because the callback will be passing an ID, we can ignore anything that does not have the unique ID we are passing.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
  if(requestCode != EXAMPLE_REWARD_ID)
      return;

  String placementTag = data.getStringExtra(PlayHavenView.BUNDLE_PLACEMENT_TAG);
  PlayHavenView.DismissType dismissType = (PlayHavenView.DismissType) data.getSerializableExtra(PlayHavenView.BUNDLE_DISMISS_TYPE);
  Toast.makeText(this, placementTag + " was dismissed: " + dismissType, Toast.LENGTH_LONG).show();
}

Content results are used in content types that collect data. This includes like Rewards, In-App Purchases, and Opt-In Data Collection.

Advanced

COPPA


If you operate a mobile app directed to children under 13 that collects, uses, or discloses personal information from children or you otherwise have actual knowledge that you are collecting, using, or disclosing personal information from children under 13, the Children’s Online Privacy Protection Act (COPPA) may apply to you. If so, you may have responsibilities relating to how you collect, disclose, or use personal information from such children.

To assist you in your data collection, disclosure and use compliance obligations, we have added to the platform (to be available in our upcoming server-side update) a new “opt-out“ setting to the Android SDK, so you can indicate whether you want Upsight to limit data collection and use, and serve only contextually targeted ads.

Child-directed settings and features

  • A default value for the opt-out flag in the SDK that can be changed by the publisher. The default value out-of-the-box will be Opt-Out = FALSE.
  • Functionality in the SDK to change the opt-out flag for the individual user. Publisher may use this setting if it utilizes age-gating functionality, for example.

WARNING It is extremely important to understand the consequences of setting the opt-out status to TRUE. By setting the opt-out status to TRUE, advertising will be limited to only contextual ads and platform data collection capabilities will be disabled. Currently, our platform only supports behavioral advertising. In the short-term, this means that when opt-out is set to TRUE, no Upsight-served ads will be available to your apps.

Example

If you have an app that is directed at 8-10 year olds, you can set the default value for the opt-out flag to be TRUE for all users. Then, you can add an age-gating mechanism to the app, and change the opt-out flag to FALSE for users that you learn to be 13 or older.

Targeting Opt-Out

To comply with COPPA regulations and standards, Upsight has provided a mechanism for your app to opt-out of collecting user information. The user opt-out status inside your app is indicated by

PlayHaven.getOptOut(Context context)
PlayHaven.setOptOut(Context context, boolean setting)

The default opt-out status is set to FALSE. If you need to opt-out of collecting user information, simply call setOptOut and set the value to TRUE.

Note Although Upsight has enabled this function, you are still responsible for providing an appropriate user interface for user opt-out.

For official information about COPPA, the recent amendments, and a list of FAQs provided by the FTC, please consult the FTC website.

Advanced

Custom Dimensions for Targeting


Custom Dimensions provide the ability to target marketing campaigns towards a customized segment of users.

Important Custom Dimensions must be created in the Upsight Marketing Dashboard before they can be integrated in the SDK. This document provides more information on creating Custom Dimensions.

To add custom dimensions to a placement, you must implement preloading. Create a Placement object and add custom dimensions to it using the addDimension method, which takes a key and value as input. The key must be a String, and the value must be either a String, Number, boolean, or null.

  • Upsight stores all custom dimensions received from the SDK on the server for each device using your app.
  • The keys that you use in the SDK must match the keys created in the Upsight Marketing Dashboard.
  • Sending the same key with a different value for a device will update the custom dimension stored on the server.
  • Sending a key with a null value for a device will delete the custom dimension stored on the server.

The following code adds custom dimensions to a content request.

// Create a new placement
Placement placement = new Placement("app_launch");

// Add dimensions before preloading the placement
placement.addDimension("gold_balance", 2170);
placement.addDimension("ua_source", "PlayHaven");
placement.addDimension("registered", true);

// Preload the placement
placement.preload(myContext);

You can also add custom dimensions in bulk by passing in a HashMap to the addDimensions method, as shown below.

// Create HashMap of custom dimensions
HashMap<String,Object> dimensions = new HashMap<String,Object>();
dimensions.put("gold_balance", 2170);
dimensions.put("ua_source", "PlayHaven");
dimensions.put("registered", true);

// Create a new placement
Placement placement = new Placement("app_launch");

// Add dimensions before preloading the placement
placement.addDimensions(dimensions);

// Preload the placement
placement.preload(myContext);

Advanced

Custom Events for Analytics


Send custom events when a user performs an action specific to your application. This action can be anything that you deem valuable to track, such as progression to another level in a game.

To send a custom event, create a CustomEvent object with data in JSON format representing the event properties you wish to track. The dictionary has the following restrictions:

  • The data must be properly formatted JSON.
  • The data size must be less than 100 KB.

It is important to note that the JSON data must conform to a specific structure in order for your events to be tracked correctly. Please use the Upsight Event Designer to construct your event data.

The Event Designer will also generate code for you to use, as shown below. This sample code sends the CustomEvent object using the CustomEventRequest class.

try{
// Create an event with raw JSON string, JSON object, Reader, etc
CustomEvent event = new CustomEvent(
"{\"inventory\":{\"swords\":{\"katanas\":3}}}");

// Create the server request
request = new CustomEventRequest(event);

// If you would like to be notified of success/failure
request.setResponseHandler(this);

// Send via your Context
request.send(this);
}catch (PlayHavenException e){
Log.e(TAG, "Error sending custom event", e);
}

Advanced

Finding Device Identifiers


How to find your Android ID

Using logcat

  1. Connect your device to your computer via USB cable.
  2. Check the console log on your computer. You can do this via logcat
  3. Open the app that you have integrated the Upsight SDK with.
  4. Search for device= in the logs.

Here is an example of the device parameter from an Upsight open call:

http://api2.playhaven.com/v3/publisher/open/?app=com.example.app&opt_out=0&app_version=unknown&os=19&hardware=Nexus%207&connection=2&idiom=2&width=557&height=320&sdk_version=2.2.2&plugin=android&languages=en_US,en&token=8267a715ecff4abcbfdd281aebeec522&device=bedb0ff7a69ddf5b&dpi=160&nonce=pQApYr1Cy-HPNCJ_8P7d1Wa6-z0&sid=2058006879690356691&sig4=kZzHIXJ4OMDgq1uzc_UO7xtnojk&tz=-7.00&scount=1&ssum=0

By searching for the device parameter in the console log, you can find the Android ID. In the example above, the Android ID is bedb0ff7a69ddf5b.

Using an App

  1. Download the free app, Android System Info, from Google Play
  2. Visit the 'System' tab at the top.
  3. Look for the Android ID listed in the OS subsection.

Advanced

In-App Purchase Tracking


You can use the Upsight SDK to track In-App Purchases (IAP) using a Virtual Goods Promotion (VGP) content unit defined in the Upsight Dashboard or from your own data. Using a VGP, if the user chooses to buy a product displayed, the product SKU is sent to your code so that you may initiate the purchase. Once the IAP has been resolved (bought, cancelled, error, etc.), you must notify Upsight using a PurchaseTrackingRequest call. You are then able to further refine your User Segmentation in the Upsight Dashboard based on the Amount Spent.

Note If you are funnelling your data from the Upsight SDK into the Upsight Analytics Dashboard, do not send both Monetization messages through the Upsight Enterprise SDK and In-App Purchase Tracking through the Upsight SDK. Doing so will cause double-counting in your purchase data. To ensure your purchase data is accurate, if you are using both the Upsight SDK and the Upsight Enterprise SDK, only send in-app purchase tracking through the Upsight SDK, not both.

To track an In-App Purchase in your application, you must have the IAP product in your dashboard. Then you can add the following to your Android app code:

  • Create a PurchaseTrackingRequest object from your Purchase object.
  • Use the object's send method to send the purchase to Upsight.

In the following example we write a reusable method called track that tracks a purchase attempt.

/**
 * Unique name for logging
 */
private static final String TAG = IAPTrackingExample.class.getSimpleName();

/**
 * For creating fake orderId and payload
 */
private static final Random random = new Random(new Date().getTime());

private void track(View target, Double price, Purchase.Result result)
{
  Purchase purchase = new Purchase();
  purchase.setSKU(getResources().getResourceName(target.getId()));
  purchase.setPrice(price);
  purchase.setStore("OurCoolStore");
  String orderId = random.nextLong() + "ABC";
  purchase.setPayload(TAG + ":" + orderId);
  purchase.setOrderId(orderId);
  purchase.setQuantity(1);
  purchase.setResult(result);
  (new PurchaseTrackingRequest(purchase)).send(this);
}

If the IAP resolves as bought, we can use the Purchase.Result.Bought result to inform the server that this particular product has been purchased successfully.

track(target, 1.50, Purchase.Result.Bought);

If the IAP resolves as already purchased, most stores will not allow the item to be purchased again. You can use the Purchase.Result.Owned result to inform the server that the item was not purchased again.

track(target, 10.00, Purchase.Result.Owned);

If the item the user is asking for no longer exists, you can use the Purchase.Result.Invalid result. This can happen if the item was disabled on the server side but the user has not upgraded their app.

track(target, 5.00, Purchase.Result.Invalid);

If the transaction has been cancelled, you can use the Purchase.Result.Cancelled result.

track(target, 1.00, Purchase.Result.Cancelled);

If the transaction returns an error, you can use the Purchase.Result.Error result.

track(target, 2.00, Purchase.Result.Error);