MAdvertiseLocation

MAdvertise Location SDK is an IOS project developed with SWIFT programming language. It help to collect and track geolcation data.


Licenses
CC0-1.0/NTP-0
Install
pod try MAdvertiseLocation

Documentation

mad_AdNetworkMediation_rgb_small.png for IOS

[TOC]

MNG Ads provides functionalities for monetizing your mobile application: from premium sales with reach media, video and innovative formats, it facilitates inserting native mobile ads as well all standard display formats. MngAds SDK is a library that allow you to handle the following Ads servers with the easy way :

It contains a dispacher that will select an ads server according to the priority and state (mngAds state diagram).

Requirements

Requires Xcode 8.

Legacy

for versions under v2.7 installing the sdk require git lfs.

#!unix

$ git lfs install —force

For more about installing git LFS go to: https://git-lfs.github.com

Version

See Change Log and Upgrade Guide.

Guidelines

See Design Guidelines and Best practices

Demo

Once you cloned/downloaded the repository, make sure to run pod install before trying to run our Demo.

Help and Troubleshooting

Help Center Answers to frequently asked questions

Using CocoaPods

The MngAds SDK is available through Cocoapods. see Using CocoaPods section.

Manual Install

  • download MngAdsSDK, you must use the according versions of Ads servers's librairies.

  • drag and drop it in your project

  • check that libMngAds.a exist in "Link Binary With Libraries"

  • For manual installation without pod, do not forget to include the "-ObjC" linker flag in "Other Linker Flags" under "Build Settings" in the project file." see our Faq

MngAds SDK needs, these libraries are in demo project :

adNetworkAdapter

You must add to your project lib[adNetworkAdapter].a and the adNetwork SDK. You must add all adapters in order to increase fillrate/revenues

You can see Installation guide for Swift

App Transport Security Settings

App Transport Security improves privacy and data integrity by ensuring your app’s network connections employ only industry-standard protocols and ciphers without known weaknesses. This helps instill user trust that your app does not accidentally leak transmitted data to malicious parties.

MNGAds SDK (with Mediation) are now ATS-compliant, but a small percentage of creatives (near to zero) not directly hosted on our platform are not.

If you must make an exception for a reason, we recommend that you minimize it by only setting the NSAllowsArbitraryLoadsInWebContent and NSAllowsArbitraryLoadsForMedia keys,

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoadsForMedia</key>
            <true/>
        <key>NSAllowsArbitraryLoadsInWebContent</key>
            <true/>
    </dict>

On December 21st, Apple announced that they have extended the ATS deadline. Previously, the deadline was January 1, 2017. The new deadline has not yet been announced. Set up the following keys in your app’s info.plist:

#!objective-c
<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>

Building Against iOS9

iOS 9 introduces changes that are likely to impact your app and its MngAds integration.

  • [Learn what's new in iOS 9 from Apple]
  • One of the changes in iOS9 is a default setting that requires apps to make network connections only over SSL (App Transport Security). Therefore Whitelist Ads Servers for Network Requests, mngAds works under https but not all adNetworks on mediation (smartAdserver, appNexus, facebook, ...). if you want to release apps that build against iOS9, you will need to disable ATS in order to ensure all mediation works too.
#!objective-c
<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>

You can also edit the plist by adding NSAppTransportSecurity key of dictionary type with a dictionary element of NSAllowsArbitraryLoads of boolean type set to �Yes�.

ats.png

  • The SDK supports bitcode. If you are using earlier versions, you must disable bitcode. But for now GoogleMobileAds.framework do not support bitcode, therefore you must disable bitcode for your app

GoogleMobileAdsSdkiOS-7.4.1/GoogleMobileAds.framework/GoogleMobileAds(GADGestureIdUtil.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.

  • FBAudienceNetwork.framework and libSmartAdServer.a do not work with Xcode 6.4. Therefore, MngAds needs Xcode 7.

Sample Application

Included is a MngAds sample app to use as example and for help on MngAds integration. This basic application allows users to test our differents formats.

Important note:

just run pod install after cloning the demo

Start Integrating

Enable Debug Mode

To enable debug mode you have to use class method setDebugModeEnabled :

 [MNGAdsSDKFactory setDebugModeEnabled:Yes];

Can you please remove debug mode on production.

Initializing the SDK

You have to init the SDK in AppDelegate.m in application:didFinishLaunchingWithOptions: This must be executed everytime you run the App

// AppDelegate.m
#import "MNGAdsSDKFactory.h"
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[MNGAdsSDKFactory initWithAppId:@"YOUR_APP_ID"];
...
}

Initialisation Delegate

MNGAds SDK is configured by server or from last configuration. So in first run after installation, initialisation take some time before be done .

To check out if the SDK is initialized or not, you have to use [MNGAdsSDKFactory isInitialized]. To know when the SDK has finished Initializing you have to use MNGAdsSDKFactoryDelegate.

// AppDelegate.h
#import "MNGAdsSDKFactory.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate,MNGAdsSDKFactoryDelegate>



// AppDelegate.m
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [MNGAdsSDKFactory initWithAppId:@"YOUR_APP_ID"];
    if([MNGAdsSDKFactory isInitialized] == NO){
        [MNGAdsSDKFactory setDelegate:self];
    }
    ...
}

-(void)MNGAdsSDKFactoryDidFinishInitializing{
    if (YOUR_APP_IS_READY_TO_SHOW_AD) {
        INIT_FACTORIES_AND_USE_THEM_TO_SHOW_ADS;
    }
}

-(void)MNGAdsSDKFactoryDidFailInitializationWithError:(NSError *)error {
    NSLog(@"MNGAds failed initialization");
}

MAdvertiseBeacon

If you plan on using Beacon in your app, please follow our MAdvertiseBeacon guide.

Timeout

The time given to the ad view to download the ad data. After this time, the dispacher stops the ad server running (with failure) and move to the next.

the default timeout is 1s.

adsFactory = [[MNGAdsSDKFactory alloc]init];
adsFactory.timeout = 3;

isBusy

Before making a request you have to check that factory not busy (handling old request).

Ads factory is busy means that it has not finished the previous request yet.

isBusy will be setted to true when factory start handling request.

isBusy will be setted to false when factory finish handling request. example:

if (bannerAdsFactory.isBusy) {
NSLog(@"Ads Factory is busy");
}else{
NSLog(@"Ads Factory is not busy");
}
[bannerAdsFactory loadBannerInFrame:CGRectMake(0, 0, 320, 50)]
if (bannerAdsFactory.isBusy) {
NSLog(@"Ads Factory is busy");
}else{
NSLog(@"Ads Factory is not busy");
}

Log:

$Ads Factory is not busy
$Ads Factory is busy

Banner

Init factory

To create a banner you have to init an object with type MNGAdsSDKFactory and set the bannerDelegate and the viewController.

bannerAdsFactory = [[MNGAdsSDKFactory alloc]init];
bannerAdsFactory.bannerDelegate = self;
bannerAdsFactory.viewController = self;

You have also to set placementId (minimum one time)

bannerAdsFactory.placementId = @"/YOUR_APP_ID/PLACEMENT_ID";
Make a request

To make a request you have to call 'loadBannerInFrame'.

[bannerAdsFactory loadBannerInFrame:kMNGAdSizeDynamicBanner]
Handle callBack from BannerDelegate

adsAdapter:bannerDidLoad: will be called by the SDK when your bannerView is ready. now you can add your bannerView to th ViewHierarchy.

-(void)adsAdapter:(MNGAdsAdapter  *)adsAdapter bannerDidLoad:(UIView  *)bannerView preferredHeight:(CGFloat)preferredHeight{
    NSLog(@"adsAdapterBannerDidLoad:");
    _bannerView = bannerView;
    _bannerView.frame = CGRectMake(0, 20, 320, preferredHeight);
    [self.view addSubview:_bannerView];
}

adsAdapter:bannerDidFailWithError: will be called when all ads servers fail. it will return the error of last called ads server.

-(void)adsAdapter:(MNGAdsAdapter *)adsAdapter bannerDidFailWithError:(NSError *)error{
NSLog(@"%@",error);
}

Some Ad Network (like Smart ads server) allow user to expand and collapse ad.

Even on refresh, banner can change the size.

adsAdapter:bannerDidChangeFrame: will be called when ad did change size

-(void)adsAdapter:(MNGAdsAdapter *)adsAdapter bannerDidChangeFrame:(CGRect)frame{
    ...
}
Handle callBack from RefreshDelegate

If you want tobe notified on refresh, you have to set refresh delegate

bannerAdsFactory.refreshDelegate = self;

On banner refresh, the SDK invoke the calback

-(void)adsAdapterBannerDidRefresh:(MNGAdsAdapter *)adsAdapter{
    ...
}

On banner fail to refresh, the SDK invoke the calback

-(void)adsAdapterBannerDidRefresh:(MNGAdsAdapter *)adsAdapter{
    ...
}

MNGAdSize

Mng ads provides variant pre-defined sizes ( example below).

/**
 MNGAdSize the same of CGRect
 */
typedef CGRect MNGAdSize;

extern MNGAdSize const kMNGAdSizeBanner; //Small Banner 320 x 50
extern MNGAdSize const kMNGAdSizeDynamicBanner; //Small Banner Screen width x 50
extern MNGAdSize const kMNGAdSizeLargeBanner; //Large Banner 320 x 100
extern MNGAdSize const kMNGAdSizeFullBanner; //Full Banner ipad 468 x 60
extern MNGAdSize const kMNGAdSizeLeaderboard; //Landscape Banner ipad 728 x 90
extern MNGAdSize const kMNGAdSizeDynamicLeaderboard; //Landscape Banner ipad Screen width x 90
extern MNGAdSize const kMNGAdSizeMediumRectangle; //Square Banner 300 x 250

Example:

    MNGAdSize size;
    if (isSquare) {
        size = kMNGAdSizeMediumRectangle;
    }else{
        BOOL isIPAD = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad);
        size = (isIPAD)?kMNGAdSizeDynamicLeaderboard:kMNGAdSizeDynamicBanner;
    }
    [bannerAdsFactory loadBannerInFrame:size];

Infeed

Init factory

To create an In-Feed Ad format ( the ads that show up in the middle of the stream as you scroll through your content), you must init an object with type MNGAdsSDKFactory and set the infeedDelegate and the viewController.

infeedAdsFactory = [[MNGAdsSDKFactory alloc]init];
infeedAdsFactory.infeedDelegate = self;
infeedAdsFactory.viewController = self;

You have also to set placementId (minimum one time)

infeedAdsFactory.placementId = @"/YOUR_APP_ID/PLACEMENT_ID";
Make a request

To make a request you have to call 'loadInfeedInFrame'.

[infeedAdsFactory loadInfeedInFrame:CGRectMake(0, 0, 320, 50)]
Handle callBack from InfeedDelegate

adsAdapter:infeedDidLoad: will be called by the SDK when your bannerView is ready. now you can add your bannerView to th ViewHierarchy.

-(void)adsAdapter:(MNGAdsAdapter  *)adsAdapter infeedDidLoad:(UIView  *)bannerView{
    NSLog(@"adsAdapterInfeedDidLoad:");
    [self.view addSubview:_bannerView];
}

NB: infeed does not return preferredHeight like banner because infeed height depends of width so you can use one the standard ration:

  • 5:3 (called also 15:9) : the one used in our demo
  • 16:9 : is the international standard format of HDTV
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    if (indexPath.row == INFEED_ROW) {
        if (_infeedView) {
            return self.view.frame.size.width * (3./5.);
        }
        return 0;
    }else{
        return OTHER_CELL_ROW_HEIGHT;
    }
}

adsAdapter:infeedDidFailWithError: will be called when all ads servers fail. it will return the error of last called ads server.

-(void)adsAdapter:(MNGAdsAdapter *)adsAdapter infeedDidFailWithError:(NSError *)error{
NSLog(@"%@",error);
}
Handle callBack from RefreshDelegate

If you want tobe notified on refresh, you have to set refresh delegate (same as banner)

infeedAdsFactory.refreshDelegate = self;

Interstitial

On info.plist if you are using "View controller-based status bar appearance" (UIViewControllerBasedStatusBarAppearance), it must be setted to YES

statusbar.png

Init factory

To create an interstitial you must init an object with type MNGAdsSDKFactory and set the interstitalDelegate and the viewController.

interstitialAdsFactory = [[MNGAdsSDKFactory alloc]init];
interstitialAdsFactory.interstitialDelegate = self;
interstitialAdsFactory.viewController = self;

You have also to set placementId (minimum one time)

interstitialAdsFactory.placementId = @"/YOUR_APP_ID/PLACEMENT_ID";
Make a request

To make a request you must call 'loadInterstitial'.

[interstitialAdsFactory loadInterstitial];
Handle callBack from InterstitialDelegate

adsAdapterInterstitialDidLoad: will be called by the SDK when your Interstitial is ready. Interstitial will be showen.

-(void)adsAdapterInterstitialDidLoad:(MNGAdsAdapter *)adsAdapter{
NSLog(@"adsAdapterInterstitialDidLoad");
...
}

adsAdapter:interstitialDidFailWithError: will be called when all ads servers fail. it will return the error of last called ads server.

-(void)adsAdapter:(MNGAdsAdapter *)adsAdapter interstitialDidFailWithError:(NSError *)error{
NSLog(@"%@",error);
}

adsAdapterInterstitialDisappear: will be called when intertisialView did disappear. now you can update your UI for example.

-(void)adsAdapterInterstitialDisappear:(MNGAdsAdapter *)adsAdapter{
NSLog(@"adsAdapterInterstitialDisappear");
//For example
HomeViewController *home =  [[HomeViewController alloc]init];
[self.navigationController pushViewController:home animated:YES];
}
Disable auto-displaying

With v2.0.4 you can disable auto-displaying.

[interstitialAdsFactory loadInterstitialWithPreferences:preferences autoDisplayed:NO];

To show the interstitial after succes you have call [displayInterstitial] that would preset the interstitial using the viewController passed to the factory, if you wish to have more control over the presentation process you could use showAdFromRootViewController.

To check if the interstitial is reday to be showen, you have to call [isInterstitialReady].

if ([interstitialAdsFactory isInterstitialReady]) {
    [interstitialAdsFactory displayInterstitial];
}

// OR
if ([interstitialAdsFactory isInterstitialReady]) {
    [interstitialAdsFactory showAdFromRootViewController:rootViewController animated:YES];
}

info: in some cases the difference between displayInterstitial and showAdFromRootViewController is a little bigger, for example in the case of smart adserver using displayInterstitial will add the the interstitial as a subview in the view of the viewController assigned to the factory, however when using showAdFromRootViewController it will present the interstitial as a viewController which is the case for most other adservers.

info: To test auto-displayin disabled on demo, you have to go to the page interstitial. others interstitials (return background, when change from page to page...) are with auto-displaying.

Native Ads

Native ads give you the control to design the perfect ad units for your app. With our Native Ad API, you can determine the look and feel, size and location of your ads. Because you decide how the ads are formatted, ads can fit seamlessly in your application.

Init factory

To create a nativeAd you have to init an object with type MNGAdsSDKFactory and set the nativeDelegate.

nativeAdsFactory = [[MNGAdsSDKFactory alloc]init];
nativeAdsFactory.nativeDelegate = self;

You have also to set placementId (minimum one time)

nativeAdsFactory.placementId = @"/YOUR_APP_ID/PLACEMENT_ID";
Make a request

To make a request you have to call 'loadNative'.

[nativeAdsFactory loadNative]
Handle callBack from NativeDelegate

adsAdapter:nativeObjectDidLoad: will be called by the SDK when your nativeObject is ready. now you can create your own view.

-(void)adsAdapter:(MNGAdsAdapter *)adsAdapter nativeObjectDidLoad:(MNGNAtiveObject *)nativeObject{
NSLog(@"adsAdapterNativeObjectDidLoad:");
self.titleLabel.text = nativeObject.title;
self.contextLabel.text = nativeObject.socialContext;
self.bodyLabel.text = nativeObject.body;
//possibility to customize the badge title
[nativeObject updateBadgeTitle:@"Publicité"];
badgeView = nativeObject.badgeView;
[nativeObject setMediaContainer:self.container];
...
}

adsAdapter:nativeObjectDidFailWithError: will be called when all ads servers fail. it will return the error of last called ads server.

-(void)adsAdapter:(MNGAdsAdapter *)adsAdapter nativeObjectDidFailWithError:(NSError *)error{
NSLog(@"%@",error);
}

See Native Ads guidelines

ClickDelegate

The clickDelegate notify you when the ad has been clicked.

//.h
@interface ViewController : UIViewController<MNGClickDelegate>

//.m
adsFactory.clickDelegate = self;

...

-(void)adsAdapterAdWasClicked:(MNGAdsAdapter *)adsAdapter{
    NSLog(@"Ad Clicked");
    ...
}

If you show an interstitial at the didEnterForeground, you can use click delegate to check up if the application enter background by user or after an ad click.

- (void)applicationDidEnterBackground:(UIApplication *)application {
    if ([self.lastClickDate timeIntervalSinceNow] >= -10.) {
        _isAdClicked = YES;
        NSLog(@"Next enter background will be ignored");
    }

}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    if ([MNGAdsSDKFactory isInitialized] && !_isAdClicked) {
        NSLog(@"applicationDidBecomeActive");
        [self displayInters];
    }
    _isAdClicked = NO;
}

-(void)adsAdapterAdWasClicked:(MNGAdsAdapter *)adsAdapter{
    NSLog(@"Banner clicked");
    [((AppDelegate*)[[UIApplication sharedApplication]delegate])setLastClickDate:[NSDate date]];
}

Preferences Object

Preferences object is an optional parameter that allow you select ads by user info. informations that you can set are:

  • age : age of user
  • location : geographical position of the user. Important: your application can be rejected by Apple if you use the device's location only for advertising.
  • language : language of user (ISO code)
  • gender : gender of user
  • keyWord : Use free-form key-values when you want to pass targeting values dynamically into an ad tag based on information you collect from your users. You can also use free-form key-values when there are too many possible values to define in advance. Separator in case of multiple entries is ;.
  • content url : URL for content related to your app (url must be a string which length not exceed 512 caracters).
  • preferredAdChoicesPosition : set the preferred adchoices position , although you need to keep in mind that in some cases it might not position it where mentioned since some of the adnetworks wont take this parameter into consideration , so preferably set the preferred position here as well in the didLoad once the request succeeds.
#!objective-c

key=value;key2=value2
#import "MNGPreference.h"
...
MNGPreference * preference = [[MNGPreference alloc]init];
preference.age = 25;
preference.language = @"fr";
preference.keyword = @"brand=myBrand;category=sport";//Separator in case of multiple entries is ; key=value
preference.gender = MNGGenderFemale;
preference.location = [[CLLocation alloc]initWithLatitude:48.876 longitude:10.453];
[preference setContentUrl:@"your content url"];
[bannerAdsFactory loadBannerInFrame:CGRectMake(0, 0, 320, 50)withPreferences:preference];

Note: this link can help you to get device location.

Error Handling

@available v2.5 Whenever an Ad fails to load, its correspondent delegate would be invoked providing an NSError object describing what went wrong, what s new in v2.5 and later versions is that we added a new Enum representing the codes of different errors along with a clear description , the different types of error can be found in top of MNGAdsSDKFactory header file :

MAdvertiseError.png

the different errors are pretty much self explanatory , and here s and example use just to remove any ambiguity there might be on how to use it :


-(void)adsAdapter:(MNGAdsAdapter *)adsAdapter nativeObjectDidFailWithError:(NSError *)error{
    NSLog(@"%@",error.localizedDescription); //will log the error's description
    if (error.code == MAdvertiseErrorWrongPlacement) {
        myFactory.placementId = @"Insert the correct placement";
        [myFactory loadNative];
    }
}

Memory managment

When you have finished your ads plant you must free the memory.

When using ARC it will be done automatically. Otherwise you have to call "releaseMemory".

ARC
[adsFactory releaseMemory];//optional
adsFactory = nil;

But we recommand to release memory in order to avoid **crashes with a "EXC_BAD_ACCESS" ** for some adNetworks.

No ARC
[adsFactory releaseMemory];//required
[adsFactory release];
adsFactory = nil;
Avoid crashes

Some adNetwork does not using Automatic Reference Counting, so you have to mange MNGAdsFactory pointer specially fo interstitial.

  • Do not call releaseMemory on viewDidDisappear

  • you have to call releaseMemory before removing pointer from current instance.

The simplest way is:

  • Calling releaseMemory before setting your property:
    [intersFactory releaseMemory];
    intersFactory = otherFactory;// Or
    intersFactory = [[MNGAdsFactory alloc]init];// Or
    intersFactory = nil;
  • Calling releaseMemory at the dealloc of delegate
    -(void)dealloc{
        [intersFactory releaseMemory];
        intersFactory = nil;
    }

Eyes tracking

available v2.6

  • the face tracking feature was implemented to determine wether the user is watching the ad or not , and for how long (in ms). this feature is optional and disabled by default, to enable it you need to include Umoove either using CocoaPods:
pod 'umooveV2framework', :git => 'https://umoove@bitbucket.org/umoove/umooveV2framework.git', :branch =>'master'

or manually:

  • download umoove.framework in your project , also you should notice that umoove is a dynamic library so you need to make sure that it s included in "Embedded Binaries" as well as "Linked Frameworks and Librairies".

Keep in mind that in order to track the user's face, the app will require the use of the device's camera , so dont forget to include NSCameraUsageDescription in your info.plist.