ayeT-Studios Publisher iOS (Objective-C) SDK Integration Guide (v1.5)



Updates

2019-07-19: v1.5 - Updated iOS SDK with adslot changes, recompiled with Swift 5, re-added x86_64 (simulator) support
2018-09-29: v1.4.2 - Updated iOS SDK to Xcode 10 and Swift 4.2, stripped debug symbols
2018-07-09: v1.4.1 - Removed Simulator Code from iOS SDK, fixed iTunes validation issues with Xcode 9+
2018-05-07: v1.4 - Framework recompiled with Swift 4.1
2018-03-08: v1.3 - You are able to use logs now in order to locate implementation problems
2018-01-20: v1.2 - Initial Release of our Publisher SDK (iOS Objective-C)


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 framework
  3. Add the framework to your Xcode project
  4. Initialize the SDK & Receive Managed Balances
  5. Check User Balances (Managed Currency Handling)
  6. Show the Offerwall
  7. Logs
  8. Appendix I: Unmanaged Currency Handling / Conversion Callbacks
  9. Appendix II: Publishing on iTunes (ERROR ITMS-90087: "Unsupported Architecture. Your executable contains unsupported architecture '[x86_64]'.")





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 iOS App Placement using the correct (Xcode) bundleId 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 SDK init call.

2. Download the framework


You can download the lastest version of our publisher library here:
AyetStudiosSDK.framework_v1.5.zip (Swift 5 ABI)

3. Add the framework to your Xcode project


Unzip the downloaded archive file, preferably inside your project directory and add the framework to your project:




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:


Please add the following to your Info.plist file:
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>	                

Select Build Settings tab and then expand Build Options. Set Always Embed Swift Standard Libraries to Yes.

Please note that this relates to your Target's Build Settings.

Also take a look at the publishing section, to make sure you're prepared to publish your archives on iTunes later:
Appendix II: Publishing on iTunes (ERROR ITMS-90087: "Unsupported Architecture. Your executable contains unsupported architecture '[x86_64]'.")

4. Initialize the SDK & Managed User Balances


First you should import Swift interface header in your *.m file:
#import "AyetStudiosSDK/AyetStudiosSDK-Swift.h"

You'll need to initialize Ayet SDK before being able to use it:
[AyetSdk sdkInitWithAppKey:<YOUR_APP_KEY> userIdentifier:<username (external identifier)> callback:^(NSInteger av, NSInteger pe, NSInteger sp) {
        //triggered after sdkInit function was called for the first time and if user currency balance changed
        NSLog(@"IBAction::initialization     =>   Available balance: %d  Pending balance: %d  Spent balance: %d" , (int)av , (int)pe , (int)sp);
}];
If you want to spend user currency, for example if the user clicks a button assigned to a purchaseInAppItem function, you can utilize the deductBalance function:
int DEDUCT_AMOUNT = 1;      // amount of currency need to be deducted

[AyetSdk deductBalanceWithAmount:DEDUCT_AMOUNT deductCallback:^(NSString* status) {
    NSLog(@"IBAction::deductBalance     =>  Deduct: %@"  , status );
}];
The status string will be "success" if the balance deduction was successful or "failed" if something went wrong (e.g. insufficient user balance).

Attention: The username or external identifier passed in the init call (e.g. username, hashed email address, etc.) will be accessible in the conversion callbacks through the {external_identifier} parameter.

5. Check User Balances (Managed Currency Handling)


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

int availableCurrency = (int) [AyetSdk getAvailableCurrency];
int pendingCurrency = (int) [AyetSdk getPendingCurrency];
int spentCurrency = (int) [AyetSdk getSpentCurrency];

NSLog(@"IBAction::logCurrentBalance     =>   Available balance: %d  Pending balance: %d  Spent balance: %d" , availableCurrency , pendingCurrency , spentCurrency);	                

6. Show the Offerwall


Showing the offerwall is straight-forward, you can simply call showOfferwall from your UIViewController:

[AyetSdk showOfferwallWithCurrentController:(self) adslotName: <MY OFFERWALL ADSLOT NAME>];	                
showOfferwall starts our offerwall and displays available tasks for the user to complete.

7. Logs


If you want to see logs in xcode debug area, simply call sdkLogEnable before initializing sdk.

[AyetSdk sdkLogEnable];	                

8. 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={external_identifier}&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=[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}floatThe amount of currency the user earned (taken from your offerwall currency configuration)
{external_identifier}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
{adslot_id}intThe id of the adslot 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
{task_name}stringOnly available for cpe campaigns, shows individual task name for that conversion.
{currency_identifier}stringShows virtual currency name as set in adslot.
{currency_conversion_rate}decimalShows currency conversion rate used to calculate user currency for the given conversion.


Postback Verification with HMAC Security Hash (optional):
Our server will always add a custom header, X-Ayetstudios-Security-Hash, containing a SHA256 HMAC hash of the request parameters and your publisher api key.
Your API key can be found in your dashboard at ayetstudios.com under settings.

To verify the hash, perform the following steps:
(1) Get all request parameters
(2) Order the request parameters alphabetically
(3) Build and compare the HMAC hash using the ordered request parameter string and your API key

PHP Example:
ksort($_REQUEST, SORT_STRING);
$sortedQueryString = http_build_query($_REQUEST, '', '&'); // "adslot_id=123&currency_amount=100&payout_usd=1.5...."
$securityHash = hash_hmac('sha256', $sortedQueryString, 'YOUR PUBLISHER API KEY');
if($_SERVER['HTTP_X_AYETSTUDIOS_SECURITY_HASH']===$securityHash) { // actually sent as X-Ayetstudios-Security-Hash but converted by apache2 in this example
    // success
}
else {
    // invalid signature
}                    


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


9. Appendix II: Publishing on iTunes (ERROR ITMS-90087: "Unsupported Architecture. Your executable contains unsupported architecture '[x86_64]'.")


iTunes does not allow uploading archives which contain unsupported architectures (which is the x86_64 simulator modules in our case).
This can easily be achieved in xCode by adding a Post Run Script to the Build Phases section in your project, making sure only the required modules are kept in our framework.
The script must be added at the end like this:



AyetStudiosSDK Clean Architectures Script:

FRAMEWORK="AyetStudiosSDK"

FRAMEWORK_EXECUTABLE_PATH="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/$FRAMEWORK.framework/$FRAMEWORK"

EXTRACTED_ARCHS=()

for ARCH in $ARCHS

do

lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"

EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")

done

lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"

rm "${EXTRACTED_ARCHS[@]}"

rm "$FRAMEWORK_EXECUTABLE_PATH"

mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"