1 About this integration guide

This integration guide provides all of the information required for technical integration and use of the  ÖWA-Library in apps that use the iOS operating system. The app platform supported here is iOS version 8.0 and above.

2 ÖWA library (iOS)

The ÖWA library for iOS provided by INFOnline (also referred to hereafter as “IOLib”) is a software library that records and saves information about the use of iOS apps and sends it to an appropriate backend for validation and monitoring.

2.1 Provision

The IOLib iOS is made available by ÖWA for download. The download includes:

  • the release notes as a text file
  • the change log as a text file
  • a directory INFOnlineLibrary: the IOLib is provided as a “framework” and can be integrated easily into existing iOS projects. For this purpose, the enclosed copy-framework script can be used.
  • a directory ObjCSample: an example project with integrated IOLib on Objective-C basis
  • a directory Swift Sample: an example project with integrated IOLib on Swift 3.2 basis

2.2 Requirements

The IOLib exclusively supports integration via the Xcode development environment under macOS.

2.2.1    Development environment

The following prerequisites must be in place to complete integration of the IOLib:

  • macOS 10.12.4 (Sierra) or higher
  • iOS SDK 11 or higher
  • Xcode 9.0 or higher
  • Objective-C or Swift

iOS apps that use the IOLib must be compiled with iOS SDK 10 as a minimum.
Deployment target must be set to a minimum of 8.0.

2.2.2    Operating system/platform

The IOLib supports operation under 32-bit and 64-bit architectures. The IOLib requires iOS 8.0 or higher to operate.

2.2.3    Compatibility

A new version of Xcode or of the operating system may require an update to the IOLib. It may not be possible to guarantee complete upward compatibility under some circumstances.

2.3 Function

2.3.1    When must the ÖWA-Library be accessed?

Accessing the functions of the IOLib within the app is linked to certain events. Specifications or recommendations about the point in the app or the user actions at which the ÖWA library should be accessed and which information should be transferred have been formulated by ÖWA for app providers.

The specifications for accessing the IOLib within the app are described in section 4 (Specifications for accessing the ÖWA library).

2.3.2    Transmission of the measurement data

The transmission of the data itself takes place asynchronously. This avoids delaying or blocking the user’s interaction with the app.

3 Integration of the ÖWA library iOS

This section describes the technical integration of the ÖWA library into an iOS project structure.

3.1 Thread-safe

The IOLib is thread-safe.

3.2 IOLib files

The ÖWA library for iOS comprises the following files

  • RELEASE_NOTES.txt
    This file includes information about the release of the IOLib.
  • CHANGE_LOG.txt
    This file includes information about the change history of the IOLib.
  • INFOnlineLibrary
    Contains the IOLib (INFOnlineLibrary.framework) for collecting the usage data of an app, as well as the copy-framework script for the automatic integration of the framework into a project.
  • ObjCSample
    An example project demonstrating the use of IOLib.
    The interaction with the IOLib is implemented with Objective-C.
    The project includes a TodayExtension.
  • SwiftSample
    An example project demonstrating the use of IOLib.
    The interaction with the IOLib is implemented with Swift 3.2.
    The project includes a TodayExtension.

3.3 Integration of the IOLib framework

Integration is carried out in just a few simple steps.

1. In the finder:

Copy the folder “INFOnlineLibrary” into the project folder (or drag it over using drag ’n’ drop)

2. In Xcode: Build Settings

Add the path to the "INFOnlineLibrary" folder to the framework search paths in the build settings.
In our sample:

$(PROJECT_DIR)/../INFOnlineLibrary/$(PLATFORM_NAME)/

For the Other Linker Flags in the build settings, the INFOnlineLibrary must be specified as follows:

-framework INFOnlineLibrary

3. In Xcode: Run Script Build Phase

Add a run script phase to the build phases:
In our sample:


${PROJECT_DIR}/../INFOnlineLibrary/copy-framework.sh

 

4.  In Xcode:

Linking of the AdSupport framework



The frameworks mentioned above must be integrated to ensure correct and complete measurement for participation in the ÖWA study. If you do not integrate the frameworks, the identifier required for the ÖWA measurement (Advertising Identifier / IDFA) cannot be transferred - participation in the ÖWA measurement is therefore not possible.

5. In Xcode:

Objective-C:
Import of the IOLib header in the ApplicationDelegate and in the ViewControllers (alternatively in the prefix header)

#import <INFOnlineLibrary/INFOnlineLibrary.h>

The umbrella header should always be used, never individual headers from the framework!

Swift:

Import of the IOLib frameworks in the ApplicationDelegate and in the ViewControllers

import INFOnlineLibrary

6. In Xcode: Initialisation and start of a session of the IOLib on application start:

Objective-C:

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(UIApplication*)application {
  [self startSession];
  // Other code
}

- (void)startSession {
  // Initialisierung der IOLib; Session-Start
  // privacySetting LIN
  [[IOLSession defaultSessionFor:IOLSessionTypeOEWA]
startSessionWithOfferIdentifier:@„<ANGEBOTSKENNUNG>" privacyType:IOLPrivacyTypeLIN];
}
// AddDelegate.m
// ObjCSample
//
// Copyright (c) 2017 RockAByte GmbH. All rights reserved
//

#import "AddDelegate.h"
#import <INFOnlineLibrary/INFOnlineLibrary.h>

NS_ASSUME_NONNULL_BEGIN

@implementation AppDelegate

-(void)applicationDidFinishLaunching:(UIApplication *)application{
  [self startSession];
}

#pragma mark - Helper

-(void)startSession{

  [IOLLogging setDebugLevel:IOLDebugLevelVerbose];

  BOOL isOptOut = [[NUserDefaults standardUserDefaults] boolForKey:@"IOLSOptOutKey"];
  if(!isOptOut) {
    [[IOLSession defaultSessionFor:IOLSessionTypeOEWA] startSessionWithOfferIdentifier:@"iamtest"
    privacyType:IOLPrivacyTypeLIN];
  }
}

@end

NS_ASSUME_NONNULL_END
Swift:

fun applicationDidFinishLaunching(_ application: UIApplication) {
  self.startSession()
  // Other code
}

func startSession() {
  // Initialisierung der IOLib; Session-Start
  // privacySetting LIN
  IOLSession.defaultSession(for: .OEWA).start(withOfferIdentifier:„“, privacyType: .LIN)
}

// AddDelegate.swift
// SwiftSample
//
// Copyright (c) 2017 RockAByte GmbH. All rights reserved
//

import UIKit
import INFOnlineLibrary

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  func applicationDidFishinLaunching(_ application: UIApplication) {
    startSession()
  }

  //MARK: - Helper
  private func startSession() {
    IOLLogging.setDebugLogLevel(.verbose)

    let isOptOut = UserDefaults.standard.bool(forKey: "IOLSOptOutKey")
    guard !isOptOut else { return }
    IOLSession.defaultSession(for: .OEWA).start(withOfferIdentifier: "iamtest",    privacyType: .LIN)
  }
}

7. In Xcode:

Events can be logged in the activities of the app, e.g. accessing a view:

Objective-C:

// Tracking View Appeared
IOLViewEvent *event = [[IOLViewEvent alloc] initWithType:IOLViewEventTypeAppeared category:@"TestCategory" comment:nil];
[[IOLSession defaultSessionFor:IOLSessionTypeOEWA] logEvent:event];
- (void)viewDidAppear:(BOOL)animated{
  [super viewDidAppear:animated];

  IOLViewEvent *event = [[IOLViewEvent alloc] initWithType:IOLViewEventTypeAppeared category:@"TestCategory" comment:nill];
  [[IOLSession defaultSessionFor:IOLSessionTypeOEWA] logEvent: event];
}
Swift:

// Tracking View Appeared
let event = IOLViewEvent(type: .appeared, category: "TestCategory", comment: nil)
IOLSession.defaultSession(for: .OEWA).logEvent(event)
override func viewDidAppear(_ animated: Bool) {
  super.viewDidAppear(animated)

  let event = IOLViewEvent(type: .appeared, category: "TestCategory", comment: nil)
  IOLSession.defaultSession(for: .OEWA).logEvent(event)
}

3.4 Parallel measurement ÖWA and INFOnline (IVW, AGOF)

The IOLib iOS supports the parallel operation of sessions of different measurement systems. In the following it shall be shown how both measurements can be operated simultaneously.

Prerequisite is an integration of the IOLib iOS according to chapter 3.3 points 1-5.

1. In Xcode: initialization and start of both sessions at application start:

Objective-C:

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(UIApplication*)application {
  [self startSessions];
  // Other code
}

- (void)startSessions {
  // Initialisierung der IOLib; Session-Start
  // privacySetting LIN
  [[IOLSession defaultSessionFor:IOLSessionTypeSZM]
    startSessionWithOfferIdentifier:@„<SZM-ANGEBOTSKENNUNG>"
    privacyType:IOLPrivacyTypeLIN];

  [[IOLSession defaultSessionFor:IOLSessionTypeOEWA]
    startSessionWithOfferIdentifier:@„<OEWA-ANGEBOTSKENNUNG>"
    privacyType:IOLPrivacyTypeLIN];
}
//
// AppDelegate.m
// ObjCSample
//
// Copyright (c) 2017 RockAByte GmbH. All rights reserved.
//

#import "AppDelegate.h"

#import <INFOnlineLibrary/INFOnlineLibrary.h>

NS_ASSUME_NONNULL_BEGIN

@implementation AppDelegate

-(void)applicationDidFinishLaunching:(UIApplication *)application {
   [self startSessions];
}

#pragma mark - Helper

- (void) startSessions{
   [IOLLogging setDebugLevel: IOLDebugLevelVerbose];

   BOOL isOptOut =[[NSUserDefaults standardUserDefaults]
     boolForKey:@"IOLSOptOutKey"];
   if (!isOptOut) {
     [[IOLSession defaultSessionFor:IOLSessionTypeSZM]
       startSessionWithOfferIdentifier:@"szmOfferID"
       privacyType: IOLPrivacyTypeLIN];
     [[IOLSession defaultSessionFor:IOLSessionTypeSZM]
       startSessionWithOfferIdentifier:@"oewaOfferID"
       privacyType: IOLPrivacyTypeLIN];
   }
}

@end

NS_ASSUME_NONNULL_END
Swift:

fun applicationDidFinishLaunching( application: UIApplication){
   self.startSessions()
   // Other code
}
func startSessions() {
   // Initialisierung der IOLib; Session-Start
   // privacySetting LIN
   IOLSession.defaultSession(for: .SZM).start(
     withOfferIdentifier:„<SZM-ANGEBOTSKENNUNG>“, privacyType: .LIN)
   IOLSession.defaultSession(for: .OEWA).start(
     withOfferIdentifier:„<OEWA-ANGEBOTSKENNUNG>“, privacyType: .LIN)
}
//
// AppDelegate.swift
// SwiftSample
//
// Copyright (c) 2017 RockAByte GmbH. All rights reserved.
//

#import UIKit
#import INFOnlineLibrary

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
   func applicationDidFinishLaunching(_ application: UIApplication){
     startSessions()
   }

   //MARK: - Helper

   private func startSessions() {
     IOLLogging.setDebugLevel(.verbose)

     let istOptOut = UserDefaults.standard.bool(forKey: "IOLSOptOutKey")
     guard !istOptOut else { return }
     IOLSession.defaultSession(for: .SZM).start(withOfferIdentifier: "szmOfferID",
       privacyType: .LIN)
     IOLSession.defaultSession(for: .OEWA).start(withOfferIdentifier: "oewaOfferID",
       privacyType: .LIN)
   }
}

2. Measure an event

Events can be logged in the view controllers of the app, e.g. the call of a view:

Objective-C:

// Tracking View Appeared
IOLViewEvent *event = [[IOLViewEvent alloc] initWithType:IOLViewEventTypeAppeared
category:@"TestCategory" comment:nil];
[[IOLSession defaultSessionFor:IOLSessionTypeSZM] logEvent:event];
[[IOLSession defaultSessionFor:IOLSessionTypeOEWA] logEvent:event];

-(void) viewDidAppear:(BOOL)animated {
   [super viewDidAppear:animated];

   IOLViewEvent *event = [[IOLViewEvent alloc] initWIthType:IOLViewEventTypeAppeared
     category: "TestCategory", comment: nil)];
   [[IOLSession defaultSessionFor:IOLSessionTypeSZM] logEvent: event]
   [[IOLSession defaultSessionFor:IOLSessionTypeOEWA] logEvent: event]
}
Swift:

// Tracking View Appeared
let event = IOLViewEvent(type: .appeared, category: "TestCategory", comment: nil)
IOLSession.defaultSession(for: .SZM).logEvent(event)
IOLSession.defaultSession(for: .OEWA).logEvent(event)
override func viewDidAppear(_ animated: Bool){
   super.viewDidAppear(animated)

   let event = IOLViewEvent(type: .appeared, category: "TestCategory", comment: nil)
   IOLSession.defaultSession(for: .SZM).logEvent(event)
   IOLSession.defaultSession(for: .OEWA).logEvent(event)
}

3.5 IOLib functions

The IOLib offers the functions described below:

3.5.1    Call the default session

All functions of the IOLib described below must be called on the default session object. The SessionType must be passed as a parameter.

Parameter:

  • IOLSessionType (mandatory)

The type of session to use. For the ÖWA measurement IOLSessionTypeOEWA must be used!

Example:
Objective-C:
+(IOLSession*)defaultSessionFor:(IOLSessionType)sessionType;


For the ÖWA measurement IOLSessionTypeOEWA must be passed as sessionType.
IOLSession *session = [IOLSession defaultSessionFor:IOLSessionTypeOEWA];
Swift:
class func defaultSession(for sessionType: IOLSessionType) -> IOLSession

For the ÖWA measurement .OEWA must be passed as sessionType.
let session = IOLSession.defaultSession(for: .OEWA)

3.5.2 Start of a session


The IOLib must be started before recording the events. In doing so, the site ID of the app and the privacy setting must be passed as a parameter.

Parameter:

  • Site ID (mandatory)

The unique service ID for the relevant app is asigned by ÖWA for each app and each operating system.

  • Privacy setting (mandatory)

Declaring the legal basis for the measurement. In case of the ÖWA always LIN.

Example (here the site ID is “iamtest” and the privacy setting is „LIN“):

Objective-C:

- (void)startSessionWithOfferIdentifier:(NSString*)offerID privacyType:(IOLPrivacyType)privacyType;

[session startSessionWithOfferIdentifier:@„iamtest“ privacyType:IOLPrivacyTypeLIN];
// AddDelegate.m
// ObjCSample
//
// Copyright (c) 2017 RockAByte GmbH. All rights reserved
//

#import "AddDelegate.h"
#import <INFOnlineLibrary/INFOnlineLibrary.h>

NS_ASSUME_NONNULL_BEGIN

@implementation AppDelegate

-(void)applicationDidFinishLaunching:(UIApplication *)application{
  [self startSession];
}

#pragma mark - Helper

-(void)startSession{

  [IOLLogging setDebugLevel:IOLDebugLevelVerbose];

  BOOL isOptOut = [[NUserDefaults standardUserDefaults] boolForKey:@"IOLSOptOutKey"];
  if(!isOptOut) {
    [IOLSession defaultSessionFor:IOLSessionTypeOEWA] startSessionWithOfferIdentifier:@"iamtest"
     privacyType:IOLPrivacyTypeLIN];
  }
}

@end

NS_ASSUME_NONNULL_END
Swift:
func start(withOfferIdentifier offerIdentifier: String, privacyType: IOLPrivacyType)

session.start(withOfferIdentifier: „iamtest“, privacyType: .LIN)
// AddDelegate.swift
// SwiftSample
//
// Copyright (c) 2017 RockAByte GmbH. All rights reserved
//

import UIKit
import INFOnlineLibrary

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  func applicationDidFishinLaunching(_ application: UIApplication) {
    startSession()
  }

  //MARK: - Helper
  private func startSession() {
    IOLLogging.setDebugLogLevel(.verbose)

    let isOptOut = UserDefaults.standard.bool(forKey: "IOLSOptOutKey")
    guard !isOptOut else { return }
    IOLSession.defaultSession(for: .OEWA).start(withOfferIdentifier: "iamtest", privacyType: .LIN)
  }
}

3.5.3  Logging an event

The measurement data is recorded by means of the logEvent call. In this case, a previously initialized event must be passed.

Objective-C:

- (void)logEvent:(IOLEvent*)event;
Swift

func logEvent(_ event: IOLEvent)

To create an event, an initializer of the corresponding IOLEvent subclass must be called. Up to four parameters can be passed, three of which are optional.

Objective-C:

- (IOL_xy_Event*)initWithType:(IOL_xy_EventType)type;
- (IOL_xy_Event*)initWithType:(IOL_xy_EventType)type category:(nullable NSString*)category comment:(nullable NSString*)comment;
- (IOL_xy_Event*)initWithType:(IOL_xy_EventType)type category:(nullable NSString*)category comment:(nullable NSString*)comment parameter:(nullable NSDictionary*)parameter;
Swift

public init(type: IOL_xy_EventType) -> IOL_xy_Event
public init(type: IOL_xy_EventType, category: String?, comment: String?) -> IOL_xy_Event
public init(type: IOL_xy_EventType, category: String?, comment: String?, parameter: [String: String]?) -> IOL_xy_Event

The first two calls are a convenience functions that opens the last-named internally.
The missing values are then completed with nil or default values.

Parameter:

  • EventType (mandatory)

The individual events can be in different states. Thus, a download can e.g. started, aborted by the user, successfully completed or terminated incorrectly.
For some events, the type parameter is omitted because only one valid type is defined for these events. The IOLCustomEvent requires the freely definable string parameter name instead of a type.

  • Category (optional): Contentpath

The contentpath is transferred in the “category” parameter. The contentpath is set by the provider. The syntactic specifications are provided in section 4.2 (Guidelines for allocation of the codes). The code is used to identify the content displayed.
Using the guidelines described in section 4 (Specifications for accessing the ÖWA library), the provider decides whether an event constitutes a valid PI as defined by the ÖWA guidelines. If an event does fall under the definition of a valid PI, it is essential to provide a contentpath. If an event does not constitute a valid PI, nil should be transmitted. This length of the field is limited to 255 characters.

  • Comment (optional)

Comment field. This field is not limited in length. Transfer of this value is optional. If it is not defined, nil should be transmitted.

  • Parameter (optional)

A dictionary with freely definable additional information about the event. Key and Value must be of type String, the maximum length is limited to 255 characters each.
Transfer of this value is optional, if it is not defined, nil should be transferred.

Verfügbare Events

The IOLib provides the following IOLEvent-derived event classes with the associated types: IOLViewEvent

  • IOLViewEventTypeAppeared

Examples:

  • IOLViewEvent/IOLViewEventTypeAppeared
Objective-C:
@implementation ViewController

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];

  IOLEvent *event = [IOLViewEvent initWithState:IOLViewEventTypeAppeared
      category:@”Home”
      comment:nil];
  [[IOLSession defaultSessionFor:IOLSessionTypeOEWA] logEvent:event];

  // Other Code ..
}
Swift:
class ViewController: UIViewController {

  override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    let event = IOLViewEvent(type: .appeared,
      category: "Home"
      comment: nil)
    IOLSession.defaultSession(for: .OEWA).logEvent(event)

    // Other Code ..
  }
}

3.5.4  Sending the measurement data

-(void)sendLoggedEvents;

The IOLib controls sending of the measurement data independently and entirely transparently. sendLoggedEvents may be accessed to force sending of the data. The IOLib then attempts to send the measured data immediately or to resend it, as soon as a data connection has been established.
Example:

Objective-C:
@implementation ViewController

- (IBAction)send:(id)sender {
   [[IOLSession defaultSessionFor:IOLSessionTypeOEWA] sendLoggedEvents];
}
Swift:
class ViewController: UIViewController {

   @IBAction func send(sender: AnyObject) {
     IOLSession.defaultSession(for: .OEWA).sendLoggedEvents()
   }
}

3.5.5  Terminate session

- (void)terminateSession;

The active session of the IOLib can be terminated explicitly. This facilitates an opt-out during the app runtime. The data collected up to that point is discarded and will not be sent.


Only use with opt-out by the user!
Examples:

Objective-C:
@implementation ViewController

- (void)disableIOLSession {
   [[IOLSession defaultSessionFor:IOLSessionTypeOEWA] terminateSession];
}
Swift:
class ViewController: UIViewController {

   func disableIOLSession() {
     IOLSession.defaultSession(for: .OEWA).terminateSession()
   }
}

The IOLib session must then be restarted! The procedure is described in section 3.5.2 (Start of a session).

3.5.6  Integration of opt-out function

The implementation is in the responsibility of the developer of the app concerned and if activated by the user, it should lead to the ÖWA library either not being initialised at all or the running session being terminated explicitly. The procedure is described in section 3.5.5. (Terminating a session).

On integration of the function, users of the app can activate and deactivate the opt-out. When the opt-out is activated, no counter impulse is triggered.


If the running session is terminated explicitly, all of the measurement data recorded up to that point but not yet sent is discarded.
If the opt-out is revised, the measurement library should be restarted. The procedure is described in section 3.5.2 (Start of a session).

3.6 Debug information

The ÖWA library can be put into debug mode for the purposes of general error analysis and, in particular, to send the measurement data. In this debug mode, the ÖWA library generates various outputs in the log flow (console).

Objective-C:
- (void)applicationDidFinishLaunching:(UIApplication*)application {
   [IOLLogging setDebugLogLevel:IOLDebugLevelInfo];
}
Swift:
func applicationDidFinishLaunching(application: UIApplication) {
   IOLLogging.setDebugLogLevel(.info)
}
The type and extent of the log outputs can be determined via a DebugLevel.
The following debug levels are defined:
  • IOLDebugLevelOff
  • ➢ Log output: Deactivated(Default)
  • IOLDebugLevelError
  • ➢ Log output: error only
  • IOLDebugLevelWarning
  • ➢ Log output: error and warnings
  • IOLDebugLevelInfo
  • ➢ Log output: error, warnings and information
  • IOLDebugLevelTrace
  • ➢ Log output: errors, warnings, information, events, requests and responses


Requests and responses are saved in the Documents folder. For debugging purposes, file sharing can be switched on in iTunes and the corresponding files simply copied via iTunes.

4 Requirements for accessing the ÖWA library

4.1 General information

Recording of the app usage by the user is carried out by the app accessing the ÖWA library when defined events take place that characterise a user interaction. The user interaction is referred to as an event.


The ÖWA library must be accessed explicitly by the app when the event occurs.

4.1.1    Interpretation of events as valid PI

The specifications listed below define how the ÖWA library is to be used in the context of the ÖWA  app measurement.

PI Events

With PI events, the event is used to generate a page impression in the same way as for the ÖWA web measurement. A contentpath must be assigned to this event (hereafter simply referred to as “CP”). This CP can subsequently be allocated to various categories and serves as the basis for creating booking units. With PI events, the ÖWA's specifications for page impressions must be attended.

4.2 Guidelines for allocation of the contentpath

For PI events, the CP must be given as a unique identifier of the content displayed. This CP is specified by the app provider.

When specifying the contentpath, the ÖWA CP-guidelines must be attended:

- Length: A CP may contain a maximum of 255 characters

- Number: A maximum of 15.000 different CPs may be used

- Permitted characters: a-z, A-Z, 0-9; comma „,“; hyphen „-“; underscore „_“; slash „/“

Detailed information of the ÖWA CP-guidelines can be found at:

http://www.oewa.at/fileadmin/Documents/documents/implementierung/oewaInfo_kategoriensystem_v1_0_1.pdf