ayeT-Studios Publisher Unity SDK Integration Guide (v1.4)



Updates

2018-12-04: v1.4 - Updated to Android SDK 3.0 - support for API 26+ build targets, bugfixes & improved handling under poor network conditions
2018-09-29: v1.3 - Updated iOS SDK to Xcode 10 and Swift 4.2, stripped debug symbols
2018-07-09: v1.2 - Removed Simulator Code from iOS SDK, fixed iTunes validation issues with Xcode 9+
2018-07-02: v1.1 - Updated Unity SDK (iOS) to Unity 2018 / Swift 4.1 / XCode 9.4, added post-install script for automatic XCode configuration
2018-01-20: v1.0 - Initial Release of our Publisher SDK (Unity)


Quick 1.3 To 1.4 Migration Guide

- remove the PACKAGE_ADDED BroadcastReceiver from AndroidManifest.xml
- add INSTALL_REFERRER BroadcastReceiver to AndroidManifest.xml (see topic 4)



Introduction

The ayeT-Studios Publisher SDK allows you to easily monetize your app and reward your users with in-app currency. Your users get access to our offerwalls, allowing them to earn currency for completing tasks such as trying new apps, answering surveys, signing up for free trials or watching video ads. The integration is simple, allows both managed (our servers store user information and balances) and unmanaged (you receive callbacks and handle user wallets yourself) currencies and also works well alongside traditional in-app purchases.




Topics

  1. Prerequisites
  2. Download The SDK
  3. Add The Package To Your Unity Project
  4. Android Specific: Update Or Create AndroidManifest.xml File
  5. Initialize The SDK & Managed User Balances
  6. Check User Balances (Managed Currency Handling)
  7. Show The Offerwall
  8. Unity Example Script
  9. Appendix I: Unmanaged Currency Handling / Conversion Callbacks
  10. Appendix II: Assets/Plugins/Android/AndroidManifest.xml Template
  11. Appendix III: Manual XCode Project Configuration





1. Prerequisites


Before integrating the SDK in your app, you should sign up for a publisher account. Afterwards login as publisher and create a new Unity App Placement using the correct package name (for iOS bundle identifier) you intend to use for your final app.
This is important since we'll generate an APP_KEY / Identifier for you which has to be added to your Unity app.

The minimum required OS version is iOS 9.0 and Android ICS 4.0 (API Level 14).

2. Download The SDK


You can download the lastest version of our publisher package here:
 AyetUnityPlugin_v1.4.unitypackage

3. Add The Package To Your Unity Project


Open your Unity project
  1. Assets -> Import Package -> Custom Package
  2. Select the AyetUnityPlugin_vVersion.unitypackage file
  3. Press the "Import" button to complete the process

4. Android Specific: Update Or Create AndroidManifest.xml File


If you're planning to build against Android, please make sure you have an AndroidManifest.xml file in Assets/Plugins/Android/. If no AndroidManifest exists, you can check out the following template: Appendix II: AndroidManifest.xml Template.

Add these app permissions to the manifest:

<uses-permission android:name="android.permission.INTERNET" /> <!-- mandatory permission -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- optional -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- optional -->	                

Add our offerwall activity to your <application> scope:

<activity android:name="com.ayetstudios.publishersdk.OfferwallActivity" android:hardwareAccelerated="true"></activity>	                

Also add the "package added" broadcast receiver right before the closing </application> tag in the AndroidManifest.xml:

<receiver android:name="com.ayetstudios.publishersdk.TrackingReceiver" android:exported="true" android:enabled="true">
    <intent-filter>
        <action android:name="com.android.vending.INSTALL_REFERRER" />
        <data android:scheme="package" />
    </intent-filter>
</receiver>	                

5. Initialize The SDK & Managed User Balances


In this step, we are going to initialize the SDK. We also use callbacks to track the user's account balance - this is optional and not required if you're planning to manage user balances on your own servers. Hin: If you do not supply a user identifier, we track account balances by device. Otherwise balances will be credited and stored for the identifier (e.g. username, hashed email address, etc.).

First, the SDK needs to be initialized like this (APP_KEY is the placement identifier in your publisher dashboard):

AyetSdk.init ("<APP_KEY>", "<EXTERNAL_USER_IDENTIFIER>", this);

Implement the SdkUserBalance interface in order to get notified when user balance changes occur:

public void userBalanceInitialized (int available_currency, int pending_currency, int spent_currency){
        Debug.Log("Your::Script::userBalanceInitialized => available_currency: " + available_currency.ToString() + "  pending_currency: "+pending_currency.ToString() + "  spent_currency: " + spent_currency.ToString() );
}
userBalanceInitialized is triggered after calling AyetSdk.init().

public void userBalanceChanged (int available_currency, int pending_currency, int spent_currency){
        Debug.Log("YourScript::userBalanceChanged => available_currency: " + available_currency.ToString() + "  pending_currency: "+pending_currency.ToString() + "  spent_currency: " + spent_currency.ToString() );
}
userBalanceChanged is triggered if the user balance changes while running the app.

If you want to spend user currency, for example if the user clicks a "purchaseInAppItem" button, you can utilize the deductUserBalance function:

AyetSdk.deductUserBalance (<DEDUCT_AMOUNT>, this);
Implement the SdkDeductCallback interface in order to get notified if a deduction succeeded:

public void deductSuccess (){
    Debug.Log ("YourScript::deductSuccess");
}
public void deductFailed (){
    Debug.Log ("YourScript::deductFailed");
}

6. Check User Balances (Managed Currency Handling)


After initializing the SDK, you can check the current user balances anywhere in your code:

AyetSdk.getAvailableCurrency();
AyetSdk.getPendingCurrency ();
AyetSdk.getSpentCurrency ();

7. Show The Offerwall


Showing the offerwall is straight-forward, you can simply call AyetSdk.showOfferwall:

AyetSdk.showOfferwall();
showOfferwall starts our offerwall activity and displays available tasks for the user to complete.

8. Unity Example Script


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ExampleScript : MonoBehaviour , SdkUserBalance  , SdkDeductCallback  {

    public void userBalanceInitialized (int available_currency, int pending_currency, int spent_currency){

        Debug.Log("ExampleScript::userBalanceInitialized => available_currency: " + available_currency.ToString() + "  pending_currency: "+pending_currency.ToString() + "  spent_currency: " + spent_currency.ToString() );
    }

    public void userBalanceChanged (int available_currency, int pending_currency, int spent_currency){

        Debug.Log("ExampleScript::userBalanceChanged => available_currency: " + available_currency.ToString() + "  pending_currency: "+pending_currency.ToString() + "  spent_currency: " + spent_currency.ToString() );
    }

    public void deductSuccess (){

        Debug.Log ("ExampleScript::deductSuccess");
    }

    public void deductFailed (){

        Debug.Log ("ExampleScript::deductFailed");
    }

    void Start () {
    }

    void Update () {

        if (Input.touchCount == 1) {

            Touch touch = Input.touches [0];

            if (touch.phase == TouchPhase.Ended) {

                if (Input.GetTouch (0).position.y > (Screen.height/2)) {

                    //sdk initialization
                    AyetSdk.init ("abcde123abcde123abcde123", "user_id_123", this);

                } else {

                    if (Input.GetTouch (0).position.x < (Screen.width/3)) {

                        //show offerwall
                        AyetSdk.showOfferwall ();
                    }
                    else if(Input.GetTouch (0).position.x > ((Screen.width/3)*2)){

                        //show user current balance
                        Debug.Log ("ExampleScript  Available currency: " + AyetSdk.getAvailableCurrency());
                        Debug.Log ("ExampleScript  Pending currency: " + AyetSdk.getPendingCurrency ());
                        Debug.Log ("ExampleScript  Spent currency: " + AyetSdk.getSpentCurrency ());
                    }
                    else {
                        int amount = 1;
                        //deduct balance
                        AyetSdk.deductUserBalance (amount, this);
                    }
                }
            }
        }

    }
}

9. Appendix I: Unmanaged Currency Handling / Conversion Callbacks


If you want to manually manage your users currencies on your own servers, you can configure a conversion callback url in our publisher dashboard.
To do so, navigate to Placements / Apps, edit your app placement and set the Callback Url to your server's postback url:


If this is the callback url your set for your app placement:
https://your-server.com/callback?network=ayetstudios&amount={currency_amount}&uid={uid}&device={advertising_id}&payout_usd={payout_usd}

A typical conversion callback sent by our server will look like this:
https://your-server.com/callback?network=ayetstudios&amount=360&uid=username&device=[GAID/IDFA]&payout_usd=0.36
* Note: This assumes you set the user identifier to username in your AyetSdk.init(..) call, the currency conversion rate in your placement was 1000 per $1 and the user completed an offer with a $0.36 payout.

Important: Your server must always reply with an HTTP 200 status code to our postbacks. Otherwise we will resend the postback 12 times over a span of one hour before giving up.

Available Macros for Postback URLs:
{transaction_id}stringUnique transaction id - use for duplicate checks
{payout_usd}floatThe actual conversion payout in USD
{currency_amount}intThe amount of currency the user earned (taken from your offerwall currency configuration)
{uid}stringThe user identifier set in your app for this user when initializing the sdk
{user_id}integerOur internal id for this offerwall user
{placement_identifier}stringThe placement_identifier for which the conversion occured
{ip}stringConverting device's IP address if known, 0.0.0.0 otherwise
{offer_id}intOffer ID of the converting offer
{offer_name}stringName / title of the converting offer
{device_uuid}stringayeT-Studios internal device identificator
{device_make}stringDevice manufacturer
{device_model}stringDevice model
{advertising_id}stringDevice advertising id (GAID/IDFA) if known, otherwise empty
{sha1_android_id}stringDevice sha1 hashed android id if known, otherwise empty
{sha1_imei}stringDevice sha1 hashed imei if known, otherwise empty


If your want to restrict postbacks to our callback server IPs, please whitelist the following IPs and check back regularly for possible changes:
35.165.166.40
35.166.159.131
52.40.3.140	    
Last IP List Update: 2017-04-07


10. Appendix II: Assets/Plugins/Android/AndroidManifest.xml Template


This is a sample AndroidManifest template in case you're not using a custom AndroidManifest file yet. Please make sure to update package, versionCode and versionName.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" android:versionCode="1" android:versionName="1.0" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal">
    <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
    <application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name">
        <activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>

        <activity android:name="com.ayetstudios.publishersdk.OfferwallActivity" hardwareAccelerated="true"></activity>

        <receiver android:name="com.ayetstudios.publishersdk.TrackingReceiver" android:exported="true" android:enabled="true">
            <intent-filter>
                <action android:name="com.android.vending.INSTALL_REFERRER" />
                <data android:scheme="package" />
            </intent-filter>
        </receiver>
    </application>
    <uses-permission android:name="android.permission.INTERNET" /> <!-- mandatory permission -->
	<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- optional -->
	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- optional -->
</manifest>	                



11. Appendix III: Manual XCode Project Configuration


Note: As of version 1.1 of the AyetUnityPlugin, this step is not required anymore and is only shown for reference, in case XCode projects are generated manually.
Normally, the Assets/Editor/AyeTPostInstall.cs script automatically applies all neccessary configuration.

To manually configure the AyeTStudios Publisher SDK for XCode, click on your project icon in the Project Navigator, select General tab and then expand Embedded Binaries. Be sure the framework you extract in your project directory is already there. If not, click the "+" symbol in the lower left of the section and add it. Repeat the same procedure for Linked Frameworks and Libraries, the final configuration should look like this:



Now select Build Settings tab. Set Always Embed Swift Standard Libraries to Yes.



Afterwards "Clean" and "Build" your project again.