Implemen­tation App iOS

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.3 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.3.
    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)/ 
kopiert!

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

-framework INFOnlineLibrary 
kopiert!

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 
kopiert!

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> 
kopiert!

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 
kopiert!

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

Objective-C:

@implementation AppDelegate

- (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions: (NSDictionary*) launchOptions {
  [self startSession];
  // Other code
  return YES;
}

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

#import "AddDelegate.h"
#import 

NS_ASSUME_NONNULL_BEGIN

@implementation AppDelegate

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary * _Nullable)launchOptions{
  [self startSession];
  return YES;
}

#pragma mark - Helper

-(void)startSession{

  [IOLLogging setDebugLevel:IOLDebugLevelVerbose];

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

@end

NS_ASSUME_NONNULL_END
kopiert!

Swift:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
  self.startSession()
  // Other code
  return true
}

func startSession() {
  // Initialisierung der IOLib; Session-Start
  // privacySetting LIN = Berechtigtes Interesse ist gegeben
  IOLSession.defaultSession(for: .OEWA).start(withOfferIdentifier:@„", privacyType: .LIN)
}
kopiert!
// AddDelegate.swift
// SwiftSample
//
// Copyright (c) 2017 RockAByte GmbH. All rights reserved
//

import UIKit
import INFOnlineLibrary

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  func application(_ application: UIApplication, didFishinLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool {
    startSession()
    return true
  }

  //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: "oewaOfferID",    privacyType: .LIN)
  }
}
kopiert!

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]; 
kopiert!
- (void)viewDidAppear:(BOOL)animated{
  [super viewDidAppear:animated];

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

Swift:

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

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

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

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
  [self startSessions];
  // Other code
  return YES;
}

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

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

#import "AppDelegate.h"

#import 

NS_ASSUME_NONNULL_BEGIN

@implementation AppDelegate

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary* _Nullable)launchOptions {
   [self startSessions];
   return YES;
}

#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 
kopiert!

Swift:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
   self.startSessions()
   // Other code
   return true
}
func startSessions() {
   // Initialisierung der IOLib; Session-Start
   // privacySetting LIN = Berechtigtes Interesse ist gegeben
   IOLSession.defaultSession(for: .SZM).start(
     withOfferIdentifier:„“, privacyType: .LIN)
   IOLSession.defaultSession(for: .OEWA).start(
     withOfferIdentifier:„“, privacyType: .LIN)
}
kopiert!
//
// AppDelegate.swift
// SwiftSample
//
// Copyright (c) 2017 RockAByte GmbH. All rights reserved.
//

#import UIKit
#import INFOnlineLibrary

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool{
     startSessions()
     return true
   }

   //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)
   }
} 
kopiert!

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];
kopiert!
-(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]
} 
kopiert!

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)
kopiert!
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)
} 
kopiert!

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]; 
kopiert!

Swift:
class func defaultSession(for sessionType: IOLSessionType) -> IOLSession

For the ÖWA measurement .OEWA must be passed as sessionType.

let session = IOLSession.defaultSession(for: .OEWA) 
kopiert!

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]; 
kopiert!
// AddDelegate.m
// ObjCSample
//
// Copyright (c) 2017 RockAByte GmbH. All rights reserved
//

#import "AddDelegate.h"
#import 

NS_ASSUME_NONNULL_BEGIN

@implementation AppDelegate

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions{
  [self startSession];
  return YES;
}

#pragma mark - Helper

-(void)startSession{

  [IOLLogging setDebugLevel:IOLDebugLevelVerbose];

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

@end

NS_ASSUME_NONNULL_END
kopiert!

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

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

import UIKit
import INFOnlineLibrary

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool {
    startSession()
    return true
  }

  //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: "oewaOfferID", privacyType: .LIN)
  }
}
kopiert!

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; 
kopiert!

Swift:

func logEvent(_ event: IOLEvent) 
kopiert!

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; 
kopiert!

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 
kopiert!

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 (mandatory): 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.

Available 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 ..
}
kopiert!

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 ..
  }
}
kopiert!

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];
}
kopiert!

Swift:

class ViewController: UIViewController {

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

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];
}
kopiert!

Swift:

class ViewController: UIViewController {

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

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). To put the IOLib into DebugMode, the method setDebugModeEnabled is called:

IOLSession.setDebugModeEnabled(true);
kopiert!

By default the Debug-Mode is deactivated, unless the Debug-Mode was explicitly activated on initialization.

Objective-C:

- (void)applicationDidFinishLaunching:(UIApplication*)application {
   [IOLLogging setDebugLogLevel:IOLDebugLevelInfo];
}
kopiert!

Swift:

func applicationDidFinishLaunching(application: UIApplication) {
   IOLLogging.setDebugLogLevel(.info)
}
kopiert!

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.

3.7 App Tracking Transparency Framework (ab iOS14)

Mit Einführung von iOS14 wird der bisherige LAT (Limit Ad Tracking) Mechanismus durch das neue Framework „App Tracking Transparency“ (ATT) abgelöst. Die IOLib unterstützt ATT ab Version 2.2.0 und respektiert die über die App einzuholende Einwilligung resp. Ablehnung der Nutzer ebenso wie die Einstellungen/Restriktionen im jeweiligen Endgerät.

Zur Erhebung des für die ÖWA-Messung erforderlichen Identifier (Advertising Identifier / IDFA) müssen Apps, welche das iOS14 SDK oder höher nutzen, die notwendigen Schritte gemäß Apple iOS Developer Dokumentation auszuführen.

Im Wesentlichen sind dies die folgenden 2 Schritte:

1. In Xcode: Neuen Key in Info.plist einfügen

In der Information Property List des Projekts muss ein neuer Key „NSUserTrackingUsageDescription“ angelegt werden:

Dieser enthält einen Text (String) zur Erläuterung der Begründung für die Abfrage zum Tracking der Werbe-ID (IDFA) durch die jeweilige App.

2. In Xcode:

Direkt nach Start der App sollte die Authorisierungsanfrage ausgelöst werden, indem die Methode „requestTrackingAuthorization“ aufgerufen wird.

Objective-C:

#import 
  ...

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(nullable NSDictionary*)launchOptions {
  [self requestIDFA];
  // start IOLSession
  return YES;
}

- (void)requestIDFA {
  [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:
  ^(ATTrackingManagerAuthorizationStatus status) {
  //Tracking authorization completed
  }];
}
kopiert!

Swift:

import AppTrackingTransparency
  ...

func application(_ application: UIApplication, didfinishlaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
  requestIDFA()
  // start IOLSession
  return true
}

private func requestIDFA() {
  ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
  // Tracking authorization completed
  })
}
kopiert!

Wird diese Anfrage zum ersten Mal gestellt, erscheint folgender Alert (Beispiel aus IOLibSample):

Der Text innerhalb des roten Rahmens entspricht exakt dem String, welcher in Schritt 1 in der Info.plist unter „NSUserTrackingUsageDescription“ definiert wurde.

Das iOS System persistiert die Wahl des Nutzer, daher erscheint dieser Alert exakt einmal. Wurde die Erlaubnis zur Abfrage in den System-Einstellungen des Gerätes global deaktiviert, dann wird der Alert nicht angezeigt.

Es ist ratsam, den App Nutzern vor Aufruf der ATT-Authorisierungsabfrage die Hintergründe dieser Abfrage ausführlicher zu erläutern. Dies könnte die Opt-in Quote deutlich erhöhen.

Da Apple die Pflicht des Einbaus der Abfrage des Advertising Identifiers auf April 2021 verschoben hat, kann eine App noch mit dem SDK13 kompiliert werden. So erscheint in der App keine ATT-Authorisierungsabfrage. Der AuthorizationStatus bleibt auf „NotDetermined“ und somit wird weiterhin der Advertising Identifier geliefert.

3.8 Hinweise zum Apple Store

Wir möchten Sie erinnern, dass seit dem 8. Dezember 2020 für den Apple App Store Datenschutzangaben verpflichtend sind. Dies gilt sowohl für neue Apps und App-Updates. Im Folgenden finden Sie sämtliche Informationen, welche in diesem Zusammenhang bereits für Sie zur Verfügung stehen.

Welche Informationen müssen für die IOLib angegeben werden?

Folgen Sie der Anleitung zum Update der App Privacy Details. Diese finden Sie unter folgendem Link:

https://help.apple.com/app-store-connect/#/dev1b4647c5b

3.8.1 Layer Datenerfassung

Frage:

Erfassen Sie oder Ihre Drittanbieter Daten von dieser App?

Auszuwählende Antwort:

Ja, wir erfassen Daten von dieser App

Auswahl Punkt Kennungen:
Geräte-ID

Auswahl Punkt :
Produktinteraktion
Werbedaten

3.8.2 Layer Geräte-ID

Frage:

Werden die von dieser App erfassten Geräte-IDs mit der Identität des Benutzers verknüpft?

Auszuwählende Antwort:

Nein, die von dieser App erfassten Geräte-IDs werden nicht mit der Identität des Benutzers verknüpft.

Frage:

Verwenden Sie oder Ihre Drittanbieter Geräte-IDs für Tracking-Zwecke?

Auszuwählende Antwort:

Ja, wir verwenden Geräte-IDs für Tracking-Zwecke

3.8.3 Layer Produktinteraktion

Frage:

Werden die von dieser App erfassten Daten zur Produktinteraktion mit der Identität des Benutzers verknüpft?

Auszuwählende Antwort:

Nein, die von dieser App erfassten Produktinteraktion werden nicht mit der Identität des Benutzers verknüpft.

Frage:

Verwenden Sie oder Drittpartner Daten zur Produktinteraktion für Tracking-Zwecke?

Auszuwählende Antwort:

Ja, wir verwenden Produktinteraktion für Tracking-Zwecke

3.8.4 Layer Werbedaten

Frage:

Werden die von dieser App erfassten Werbedaten mit der Identität des Benutzers verknüpft?

Auszuwählende Antwort:

Nein, die von dieser App erfassten Werbedaten werden nicht mit der Identität des Benutzers verknüpft.

Frage:

Verwenden Sie oder Ihre Drittpartner Werbedaten für Tracking-Zwecke?

Auszuwählende Antwort:

Ja, wir verwenden Werbedaten für Tracking-Zwecke

3.8.5 Layer Gesamtübersicht

In diesem Layer sehen Sie nochmal den Überblick Ihrer Eingaben.

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:

ÖWA Categories