Открыть меню
Открыть персональное меню
Вы не представились системе
Your IP address will be publicly visible if you make any edits.

ЕдиныйАгент SDK для iOS

Материал из Документация АппОптима

Используйте ЕдиныйАгент SDK для iOS, чтобы сообщать дополнительные сведения о сеансах пользователей в своем мобильном приложении. ЕдиныйАгент SDK для iOS позволяет создавать настраиваемые действия (custom actions), измерять веб-запросы, сообщать об ошибках и помечать конкретных пользователей. В разделах ниже объясняется, как включить эти возможности.


Для iOS ЕдиныйАгент SDK доступен автоматически после добавления АппОптима CocoaPod в проект. Вы можете использовать ЕдиныйАгент SDK для iOS в Swift и Objective-C.

1. Запуск ЕдиныйАгент

Чтобы отключить автоматический запуск ЕдиныйАгент, установите ключ конфигурации DTXAutoStart в false в файле Info.plist вашего приложения:

<key>DTXAutoStart</key>

<false/>


После этого вы можете запустить ЕдиныйАгент вручную, используя либо конфигурацию Info.plist, либо переданный словарь конфигурации.

Важно

Мы рекомендуем запускать ЕдиныйАгент как можно раньше, например, в applicationWillFinishLaunching.

2. Запуск ЕдиныйАгент с конфигурацией Info.plist

Если вы хотите запустить ЕдиныйАгент с настройками из файла Info.plist, используйте вызов API startupWithInfoPlistSettings.

Swift Objective-C
АппОптима.startupWithInfoPlistSettings() [АппОптима startupWithInfoPlistSettings];

3. Запуск ЕдиныйАгент с переданным словарем конфигурации

Если вы хотите запустить ЕдиныйАгент с переданным словарем конфигурации, используйте вызов API startupWithConfig. Ключи конфигурации для словаря такие же, как и для файла Info.plist, и их также можно найти в заголовочном файле АппОптима.h, поставляемом с ЕдиныйАгент.

Swift Objective-C
let startupDictionary: [String : Any?] = [

kDTXApplicationID: "aaaa-bbbb-cccc-dddd-eeee-ffff",

kDTXBeaconURL: "https://my.beacon.url/mbeacon",

kDTXLogLevel: "WARNING"

]

АппОптима.startup(withConfig: startupDictionary)

NSDictionary<NSString*, id> *startupDictionary = @{

kDTXApplicationID: @"aaaa-bbbb-cccc-dddd-eeee-ffff",

kDTXBeaconURL: @"https://my.beacon.url/mbeacon",

kDTXLogLevel: @"WARNING"

};

[АппОптима startupWithConfig:startupDictionary];

Важно

Может потребоваться указать дополнительные параметры. Чтобы узнать, какие параметры и значения необходимо указать, проверьте instrumentation wizard в веб-интерфейсе АппОптима.

4. Создание настраиваемых действий (custom actions)

Вы можете определять и направлять настраиваемые действия (custom actions). После того, как вы их запустите, их можно дополнить дополнительной информацией, прежде чем закрыть их.

5. Запуск и закрытие настраиваемых действий (custom actions)

Ниже приведен фрагмент кода, который показывает, как запустить и закрыть настраиваемое действие. Обратите внимание, что ЕдиныйАгент отбрасывает все данные мониторинга, связанные с действием, если настраиваемое действие не закрыто. Время измеряется автоматически.

Swift Objective-C
// start the "Tap on Search" action

let action = DTXAction.enter(withName: "Tap on Search")

// ...do some work here...

// close the "Tap on Search" action

action?.leave()

// start the "Tap on Search" action

DTXAction *action = [DTXAction enterActionWithName:@"Tap on Search"];

// ...do some work here...

// close the "Tap on Search" action

[action leaveAction];


Для мобильного настраиваемого действия, созданного пользователем, или для мобильного автоматически сгенерированного пользовательского действия (user action), максимальная длина имени составляет 250 символов.

Максимальная продолжительность мобильного настраиваемого действия составляет 9 минут.

Если настраиваемое действие занимает более 9 минут и не закрывается, оно отбрасывается и не отправляется в АппОптима.


Вы можете выполнять следующие операции мониторинга с настраиваемым действием:

5.1. Создать дочернее действие

Дочерние действия аналогичны родительским действиям. Когда родительское действие закрывается, ЕдиныйАгент автоматически закрывает все дочерние действия родительского действия.

Фрагмент кода ниже показывает, как запустить действие в качестве дочернего элемента другого действия.

Swift Objective-C
// start a parent custom action

let searchAction = DTXAction.enter(withName: "Tap on Search")

// ...do some work here...

// start a child action

let parseAction = DTXAction.enter(withName: "Tap on Confirm", parentAction: searchAction)

// ...do some work here...

// close a child action

parseAction?.leave()

// ...do some work here...

// close a parent custom action

searchAction?.leave()

// start a parent custom action

let searchAction = DTXAction.enter(withName: "Tap on Search")

// ...do some work here...

// start a child action

let parseAction = DTXAction.enter(withName: "Tap on Confirm", parentAction: searchAction)

// ...do some work here...

// close a child action

parseAction?.leave()

// ...do some work here...

// close a parent custom action

searchAction?.leave()// start a parent custom action

DTXAction *searchAction = [DTXAction enterActionWithName: @"Tap on Search"];

// ...do some work here...

// start a child action

DTXAction *parseAction = [DTXAction enterActionWithName: @"Tap on Confirm" parentAction: searchAction];

// ...do some work here...

// close a child action

[parseAction leaveAction];

// ...do some work here...

// close a parent custom action

[searchAction leaveAction];


Для настраиваемого мобильного действия (custom action) или мобильного действия пользователя (user action), сгенерированного автоматически, максимальная длина имени составляет 250 символов.

5.1.1. Пример пользовательского действия

В следующем фрагменте кода показан пример ручного инструментирования.

Swift Objective-C
func countParameters(query: String?) -> Int {

var count: Int = 0

//create a parent custom action

let checkQueryAction = DTXAction.enter(withName: "Tap on Check query")

//report a value on an action

checkQueryAction?.reportValue(withName: "query", stringValue: String(describing: query))

let countParametersAction = DTXAction.enter(withName: "Count parameters", parentAction: checkQueryAction)

if let query = query {

count = query.components(separatedBy:"&").count

//report a value

countParametersAction?.reportValue(withName: "Parameters found", intValue: Int64(count))

//close a child action

countParametersAction?.leave()

} else {

//report an event

countParametersAction?.reportEvent(withName: "No parameters found")

//close a child action

countParametersAction?.leave()

//report an error

checkQueryAction?.reportError(withName: "Query was nil", errorValue: -42)

}

//close a parent custom action - automatically closes all open child actions if not closed by API

checkQueryAction?.leave()

return count

}

func countParameters(query: String?) -> Int {

var count: Int = 0

//create a parent custom action

let checkQueryAction = DTXAction.enter(withName: "Tap on Check query")

//report a value on an action

checkQueryAction?.reportValue(withName: "query", stringValue: String(describing: query))

let countParametersAction = DTXAction.enter(withName: "Count parameters", parentAction: checkQueryAction)

if let query = query {

count = query.components(separatedBy:"&").count

//report a value

countParametersAction?.reportValue(withName: "Parameters found", intValue: Int64(count))

//close a child action

countParametersAction?.leave()

} else {

//report an event

countParametersAction?.reportEvent(withName: "No parameters found")

//close a child action

countParametersAction?.leave()

//report an error

checkQueryAction?.reportError(withName: "Query was nil", errorValue: -42)

}

//close a parent custom action - automatically closes all open child actions if not closed by API

checkQueryAction?.leave()

return count

}

5.2. Отменить действие

ЕдиныйАгент для iOS версии 8.229+

Вы можете отменить настраиваемое действие или автоматически сгенерированное действие пользователя. При отмене действия удаляются все связанные с ним данные: все сообщаемые значения отбрасываются, а все дочерние действия отменяются.

Важно

Нельзя отменить закрытое действие, поэтому вызов cancel/cancelAction после leave/leaveAction для того же действия невозможен. То же самое касается закрытия отмененного действия: вы не можете вызвать leave/leaveAction после использования cancel/cancelAction для того же действия.

Swift Objective-C
// start the "Tap on Search" action

let action = DTXAction.enter(withName: "Tap on Search")

// ...do some work here...

// cancel the "Tap on Search" action

action?.cancel()

// start the "Tap on Search" action

DTXAction *action = [DTXAction enterActionWithName:@"Tap on Search"];

// ...do some work here...

// cancel the "Tap on Search" action

[action cancelAction];

5.3. Сообщить о событии

С помощью reportEvent вы можете сообщить о конкретном событии. Событие должно принадлежать настраиваемому пользовательскому действию или автоматически сгенерированному действию пользователя. Сообщенные события отображаются в каскадном анализе (waterfall analysis) действий пользователя.

Swift Objective-C
let myAction = DTXAction.enter(withName: "My action")

myAction?.reportEvent(withName: "Something important just happened")

myAction?.leave()

// report an event

- (DTX_StatusCode) reportEventWithName:(NSString *)eventName


Если вы хотите сообщать об отдельных событиях с большим количеством дополнительной информации, см. раздел Отчет о бизнес-событии.

5.4. Сообщить об ошибке

С помощью reportError вы можете сообщить о конкретном событии как об ошибке.

Существует два варианта сообщения об ошибке:

Сообщенные ошибки (как отдельные (standalone), так и «прикрепленные» (attached) к действию пользователя) отображаются на странице сведений о сеансе пользователя и многомерной странице анализа действий пользователя (multidimensional User action analysis). Сообщенные ошибки, являющиеся частью действия пользователя, также отображаются в каскадном анализе действий пользователя (user action waterfall analysis).

Вы можете сообщить об ошибке с помощью кода ошибки, исключения или NSError.

Swift Objective-C
Автономная (standalone) ошибка (не привязанная к конкретному действию пользователя)

DTXAction.reportError(withName: "My custom error", error: NSError(domain: "Global issue", code: 007, userInfo: nil))

Ошибка связана с конкретным действием пользователя

let myAction = DTXAction.enter(withName: "My action")

myAction?.reportError(withName: "My custom error", error: NSError(domain: "Action issue", code: 007, userInfo: nil))

myAction?.leave()

// report an error

DTXAction *action;

NSError* error;

[action reportErrorWithName:@"CommunicationError" errorValue:[error code]];

5.5. Сообщить значение

Метод reportValue позволяет вам сообщать свои собственные показатели. Эти показатели должны быть частью настраиваемого действия (custom action) или автоматически сгенерированного действия пользователя (user action). Сообщаемые значения отображаются в каскадном анализе действий пользователя (user action waterfall analysis).

ЕдиныйАгент SDK позволяет сообщать значения int, double и string.

Swift Objective-C
let myAction = DTXAction.enter(withName: "My action")

myAction?.reportValue(withName: "My int value", intValue: 1234)

myAction?.reportValue(withName: "My double value", doubleValue: 12.34)

myAction?.reportValue(withName: "My string value", stringValue: "Hello World!")

myAction?.leave()

let myAction = DTXAction.enter(withName: "My action")

myAction?.reportValue(withName: "My int value", intValue: 1234)

myAction?.reportValue(withName: "My double value", doubleValue: 12.34)

myAction?.reportValue(withName: "My string value", stringValue: "Hello World!")

myAction?.leave()- (DTX_StatusCode) reportValueWithName:(NSString *)valueName

intValue:(NSInteger)value

- (DTX_StatusCode) reportValueWithName:(NSString *)valueName

doubleValue:(double)doubleValue

- (DTX_StatusCode) reportValueWithName:(NSString *)valueName

stringValue:(NSString *)stringValue

5.6. Отчет о бизнес-событии

ЕдиныйАгент для iOS версии 8.253+

С помощью метода sendBizEvent вы можете сообщать о бизнес-событиях. Эти события являются самостоятельными (standalone), так как ЕдиныйАгент отправляет их отдельно от пользовательских действий (user actions) или пользовательских сессий (user session).

Swift Objective-C
let attributes: [String: Any] = [

"event.name": "Confirmed Booking",

"screen": "booking-confirmation",

"product": "Danube Anna Hotel",

"amount": 358.35,

"currency": "USD",

"reviewScore": 4.8,

"arrivalDate": "2022-11-05",

"departureDate": "2022-11-15",

"journeyDuration": 10,

"adultTravelers": 2,

"childrenTravelers": 0

]

АппОптима.sendBizEvent(withType: "com.easytravel.funnel.booking-finished", attributes: attributes)

NSDictionary<NSString*, id> *attributes = @{

@"event.name": @"Confirmed Booking",

@"screen": @"booking-confirmation",

@"product": @"Danube Anna Hotel",

@"amount": @358.35,

@"currency": @"USD",

@"reviewScore": @4.8,

@"arrivalDate": @"2022-11-05",

@"departureDate": @"2022-11-15",

@"journeyDuration": @10,

@"adultTravelers": @2,

@"childrenTravelers": @0

};

[АппОптима sendBizEventWithType: @"com.easytravel.funnel.booking-finished" attributes: attributes];

6. Измерение веб-запросов

Для отслеживания веб-запросов ЕдиныйАгент добавляет каждому запросу HTTP заголовок x-АппОптима с уникальным значением. Это необходимо для сопоставления данных мониторинга на стороне сервера с соответствующим мобильным веб-запросом. Кроме того, измеряются временные значения с мобильной стороны.

ЕдиныйАгент для iOS автоматически определяет время веб-запросов, сделанных с использованием NSURLRequest, NSURLConnection, NSURLSession, NSURLProtocol, NSString, WKWebView или NSData. Однако в следующих случаях вам необходимо вручную инструментировать запросы:

6.1. Какой тип инструментирования использовать

Для HTTP(S)-запросов нельзя комбинировать автоматическое и ручное инструментирование веб-запросов. Однако вы можете использовать автоматическое инструментирование для HTTP(S)-запросов и ручное инструментирование для не-HTTP(S)-запросов, таких как запросы WebSocket или gRPC.

В приведенной ниже таблице объясняется, какой тип инструментирования запроса следует использовать в зависимости от того, какие типы запросов есть в вашем приложении. Он также показывает, следует ли отключать автоматическую обработку запросов.

Тип запроса Тип инструмента DTXInstrumentWebRequestTiming
Только HTTP(S) Option A

Авто

true
Option B

Вручную

false
Только не-HTTP(S) Вручную false (необязательный)
HTTP(S) + не-HTTP(S) Option A

Автоматически для HTTP(S) и вручную для не-HTTP(S)

True
Option B

Вручную

False

6.2. Родительское действие веб-запросов

Существует предопределенный порядок, которому следует ЕдиныйАгент для iOS для определения родителя события веб-запроса, который влияет на то, как веб-запросы отображаются в каскадном анализе (waterfall analysis).

Автоматическая инструментация веб-запросов.

  • Если есть активное настраиваемое действие (custom action), запущенное в том же потоке, что и веб-запрос, это действие является родительским.
  • Если активного настраиваемого действия (custom action) нет, но есть активное автоматически созданное действие (autogenerated action), то автоматически созданное действие (например, Touch on...) является родительским действием. Это включает в себя автоматически сгенерированное действие Loading ...
  • Если ЕдиныйАгент не может найти активное действие, событие веб-запроса является событием корневого уровня, не имеющим родительского действия.

Ручная инструментация веб-запросов.

  • Если родительское действие не указано (АппОптима.getRequestTagValue(for: url)), то поведение для поиска родительского действия такое же, как и для автоматического определения времени веб-запроса.
  • Если указано родительское действие (childAction?.getTagFor(url)), то это действие является родительским.

6.3. Пример: упрощенная ручная инструментация веб-запросов

import UIKit

import WebKit

import АппОптима

class ViewController: UIViewController {

override func viewDidLoad() {

super.viewDidLoad()

let wkWebView = WKWebView(frame: self.view.frame)

self.view.addSubview(wkWebView)

manualTaggingDemo(wkWebView: wkWebView)

}

func manualTaggingDemo(wkWebView: WKWebView) {

let parentAction = DTXAction.enter(withName: #function)

let url = URL(string: "https://www.АппОптима.com")

downloadRequest(url: url!, wkWebView: wkWebView, parentAction: parentAction) //as this is async parent action should be left when request is done

}

func downloadRequest(url: URL, wkWebView: WKWebView, parentAction: DTXAction?) {

let childAction = DTXAction.enter(withName: #function, parentAction: parentAction) //add child action to see method call trace

let session = URLSession.shared

let request = NSMutableURLRequest(url: url)

request.httpMethod = "GET"

request.cachePolicy = .reloadIgnoringCacheData

var webrequestTiming: DTXWebRequestTiming?

//if let АппОптимаHeaderValue = АппОптима.getRequestTagValue(for: url) { //let agent decide which action it uses as parent (last created action)

if let АппОптимаHeaderValue = childAction?.getTagFor(url) { //provide parent action

let АппОптимаHeaderKey = АппОптима.getRequestTagHeader() //this could be cached as it always is x-АппОптима

request.addValue(АппОптимаHeaderValue, forHTTPHeaderField: АппОптимаHeaderKey)

webrequestTiming = DTXWebRequestTiming.getDTXWebRequestTiming(АппОптимаHeaderValue, request: url)

}

let task = session.downloadTask(with: request as URLRequest) {

(location, response, error) in

defer {

parentAction?.leave() //leave parent action when request finished - all child actions are automaticlly left on leaving parent

}

guard let _:URL = location, let _:URLResponse = response, error == nil else {

webrequestTiming?.stop("failed") //stop webrequest timing in error case

return

}

let urlContents = try! String(contentsOf: location!, encoding: .utf8)

guard !urlContents.isEmpty else {

webrequestTiming?.stop("empty content") //stop webrequest timing in error case

return

}

webrequestTiming?.stop((response as! HTTPURLResponse).statusCode.description) //stop webrequest when request finished

DispatchQueue.main.async {

wkWebView.loadHTMLString(urlContents, baseURL: nil)

}

}

webrequestTiming?.start() //start webrequest timing

task.resume()

}

}

6.4. Мониторинг запросов, отличных от HTTP(S)

ЕдиныйАгент для iOS не поддерживает автоматическую обработку запросов, отличных от HTTP(S). Если вам нужно сообщить о таких запросах, как запрос WebSocket (начинается с ws:// или wss://), проверьте следующие примеры кода.

Важно
  • Если у вас есть только не-HTTP(S) запросы, вы можете отключить автоматическое инструментирвоание запросов, но на самом деле это не обязательно.
  • Если у вас есть как HTTP(S), так и не-HTTP(S) запросы, а HTTP(S) запросы автоматически инструментируются, не отключайте автоматическое инструментирование запросов.
Swift
import UIKit

import АппОптима

class ViewController: UIViewController {

override func viewDidLoad() {

let parentAction = DTXAction.enter(withName: #function)!

defer { parentAction.leave() }

webSocketMonitoringExample(parentAction: parentAction)

}

func webSocketMonitoringExample(parentAction : DTXAction) {

let childAction = DTXAction.enter(withName: #function, parentAction: parentAction)

defer { childAction?.leave() }

let urlSession = URLSession(configuration: .default)

let url = URL(string: "wss://....")! // example echo wss server

let tag = childAction?.getTagFor(url)! // not sending the tag, just using it for internal reference

let webrequestTiming = DTXWebRequestTiming.getDTXWebRequestTiming(tag!, request: url)

let webSocketTask = urlSession.webSocketTask(with: url)

webSocketTask.resume()

webrequestTiming?.start()

let message = URLSessionWebSocketTask.Message.string("Hello World")

webSocketTask.send(message) { error in

if let error = error {

print("send error: \(error.localizedDescription)")

}

}

// synchronous example

let receiveDispatch = DispatchGroup()

receiveDispatch.enter()

webSocketTask.receive { result in

print("received data: \(result)")

receiveDispatch.leave()

}

receiveDispatch.wait()

webSocketTask.cancel()

webrequestTiming?.stop(String(URLSessionWebSocketTask.CloseCode.normalClosure.rawValue))

}

}

Objective-C
#import "ViewController.h"

#import <АппОптима/АппОптима.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

DTXAction* parent = [DTXAction enterActionWithName: [NSString stringWithFormat:@"%s", __FUNCTION__]];

[self webSocketMonitoringExample:parent];

[parent leaveAction];

}

- (void)webSocketMonitoringExample:(DTXAction*)parentAction {

DTXAction* childAction = [DTXAction enterActionWithName:[NSString stringWithFormat:@"%s", __FUNCTION__] parentAction:parentAction];

NSURLSession* urlSession = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.defaultSessionConfiguration];

NSURL* url = [NSURL URLWithString:@"wss://...."]; // example echo wss server

NSString* tag = [childAction getTagForURL:url]; // not sending the tag, just using it for internal reference

DTXWebRequestTiming* webrequestTiming = [DTXWebRequestTiming getDTXWebRequestTiming:tag requestUrl:url];

NSURLSessionWebSocketTask* webSocketTask = [urlSession webSocketTaskWithURL:url];

[webSocketTask resume];

[webrequestTiming startWebRequestTiming];

NSURLSessionWebSocketMessage* message = [[NSURLSessionWebSocketMessage alloc] initWithString:@"Hello World"];

[webSocketTask sendMessage:message completionHandler:^(NSError * _Nullable error) {

if (error) {

NSLog(@"send error: %@", error.localizedDescription);

}

}];

// synchronous example

dispatch_group_t receiveDispatch = dispatch_group_create();

dispatch_group_enter(receiveDispatch);

[webSocketTask receiveMessageWithCompletionHandler:^(NSURLSessionWebSocketMessage * _Nullable message, NSError * _Nullable error) {

NSLog(@"received data: %@", message);

dispatch_group_leave(receiveDispatch);

}];

dispatch_group_wait(receiveDispatch, DISPATCH_TIME_FOREVER);

[webSocketTask cancel];

[webrequestTiming stopWebRequestTiming:[NSString stringWithFormat:@"%ld", (long)NSURLSessionWebSocketCloseCodeNormalClosure]];

[childAction leaveAction];

}

@end

6.5. Отключить автоматическое инструментирвоание запросов

Чтобы отключить автоматическое инструментирование веб-запросов, установите для ключа конфигурации DTXInstrumentWebRequestTiming значение false.

7. Отметить конкретных пользователей тегом.

Вы можете отметить каждого пользователя своих мобильных приложений уникальным именем пользователя. Это позволяет вам искать и фильтровать определенные сеансы пользователей и анализировать поведение отдельных пользователей с течением времени.

Следующие шаги объясняют, как вручную отметить отдельного пользователя с помощью АппОптима API. Вы можете отметить пользователей при входе в систему или когда уже открытая сессия используется или восстанавливается при повторном запуске приложения, поскольку тег не сохраняется при перезапуске приложения.

Swift Objective-C
АппОптима.identifyUser("userId") [АппОптима identifyUser:@"userId"];
Важно

ЕдиныйАгент для iOS версии 235+

Сеансы, разделенные из-за бездействия или истечения времени продолжительности, автоматически переопределяются (re-tagged).

Когда ЕдиныйАгент завершает помеченный сеанс из-за того, что продолжительность сеанса достигла установленного предела, или из-за бездействия пользователя, последующий сеанс автоматически повторно помечается. Вам не нужно снова предоставлять информацию об идентификации пользователя.

Однако следует отметить, что ЕдиныйАгент не переопределяет метку следующего сеанса в следующих случаях:

  • Когда вы явно завершаете помеченный пользовательский сеанс через endVisit
  • Когда пользователь или мобильная операционная система закрывает или принудительно останавливает приложение
  • Когда ЕдиныйАгент завершает текущий сеанс пользователя и создает новый сеанс после изменения настроек конфиденциальности.

8. Завершение сессии

Вы можете принудительно завершить сеанс с помощью АппОптима API. Это также закрывает все открытые действия и запускает новый сеанс.

Swift Objective-C
АппОптима.endVisit() [АппОптима endVisit];

9. Настроить конфиденциальность данных

В режиме согласия пользователя для мобильных приложений (user opt-in) вы можете динамически настраивать параметры конфиденциальности данных и создавать свои приложения в соответствии с законами и нормами о защите данных.

Чтобы активировать режим согласия пользователя (user opt-in), добавьте ключ конфигурации DTXUserOptIn в файл Info.plist вашего приложения:

<key>DTXUserOptIn</key>

<true/>

В следующих примерах кода показано, как работать с API:

Swift Objective-C
import АппОптима

let privacyConfig = АппОптима.userPrivacyOptions()

privacyConfig.dataCollectionLevel = .userBehavior

privacyConfig.crashReportingOptedIn = true

privacyConfig.crashReplayOptedIn = true

АппОптима.applyUserPrivacyOptions(privacyConfig) { (successful) in

// callback after privacy changed

}

#import <АппОптима/АппОптима.h>

id<DTXUserPrivacyOptions> privacyConfig = [АппОптима userPrivacyOptions];

privacyConfig.dataCollectionLevel = DTX_DataCollectionUserBehavior;

privacyConfig.crashReportingOptedIn = YES;

privacyConfig.crashReplayOptedIn = YES;

[АппОптима applyUserPrivacyOptions:privacyConfig completion:^(BOOL successful) {

// callback after privacy changed

}];


Доступны следующие уровни сбора данных:

  • off/DTX_DataCollectionOff
  • performance/DTX_DataCollectionPerformance
  • userBehavior/DTX_DataCollectionUserBehavior
Важно

ЕдиныйАгент сохраняет настройки конфиденциальности данных и автоматически применяет их при перезапуске приложения. Каждый раз, когда пользователь меняет уровень сбора данных, ЕдиныйАгент создает новый сеанс с новыми настройками. Убедитесь, что вы не обертываете этот метод API с действием пользователя, в противном случае ЕдиныйАгент не сможет привязать действие пользователя к правильному сеансу.

Вы также можете использовать те же свойства для получения параметров конфиденциальности данных:

Swift Objective-C
import АппОптима

let privacyOptions = АппОптима.userPrivacyOptions()

let dataCollectionLevel = privacyConfig.dataCollectionLevel

let crashReporting = privacyConfig.crashReportingOptedIn

let crashReplay = privacyConfig.crashReplayOptedIn

#import <АппОптима/АппОптима.h>

id<DTXUserPrivacyOptions> privacyConfig = [АппОптима userPrivacyOptions];

DTX_DataCollectionLevel level= privacyConfig.dataCollectionLevel;

BOOL crashReporting = privacyConfig.crashReportingOptedIn;

BOOL crashReplay = privacyConfig.crashReplayOptedIn;

10. Именование действий пользователя

Чтобы создать имена действий пользователя (user action name), ЕдиныйАгент захватывает заголовок элемента управления UIButton, оценивая следующий порядок API или полей и останавливаясь, как только получает действительный текст:

  1. titleLabel.attributedText
  2. attributedTitleForState:UIControlStateNormal
  3. accessibilityLabel

Если ни один из них не содержит полезного текста, ЕдиныйАгент устанавливает заголовок элемента управления в значение по умолчанию Button.

Для ячеек таблиц происходит аналогичное поведение: используется эвристика для определения самой заметной метки в ячейке, и ЕдиныйАгент использует этот текст в имени действия пользователя.

11. Использование пользовательских заголовков управления (Use custom control titles)

Вы можете переопределить захваченные заголовки элементов управления UIControl, UITableViewCell и UICollectionViewCell. Это позволяет вам изменять заголовки элементов управления или скрывать их по причинам конфиденциальности.

Если вы предоставите пустую строку, ЕдиныйАгент будет использовать тип элемента управления в имени действия пользователя, например, Touch on Button. Если вы предоставите nil, заголовок элемента управления будет сброшен на значение по умолчанию.

Swift Objective-C
var button: UIButton

button.dtxCustomControlName("Custom button title")

var tableCell: UITableViewCell

tableCell.dtxCustomCellName("Custom table cell title")

var collectionCell: UICollectionViewCell

collectionCell.dtxCustomCellName("Custom collection cell title")

UIButton *button;

[button dtxCustomControlName:@"Custom button title"];

UIButton *tableCell;

[tableCell dtxCustomCellName:@"Custom table cell title"];

UIButton *collectionCell;

[collectionCell dtxCustomCellName:@"Custom collection cell title"];


Если вы хотите избавиться от заголовков управления во всех действиях пользователей одновременно, см. раздел Маскирование пользовательских действий.

12. Изменение автоматически созданных действий

ЕдиныйАгент для iOS версии 8.241+

ЕдиныйАгент для iOS создает действия пользователя на основе взаимодействия пользователей вашего приложения. Эти действия отличаются от настраиваемых действий (custom actions) и иногда называются автоматически сгенерированными действиями (autogenerated actions). Мы также называем их действиями пользователя (user actions).

Используя ЕдиныйАгент SDK для iOS, вы можете изменить или даже отменить эти автоматически созданные действия.

Если вы хотите избежать захвата персональной информации для всех действий пользователя одновременно, обратитесь к разделу Маскирование пользовательских действий.

12.1. Изменение конкретного действия пользователя

ЕдиныйАгент для iOS версии 8.215+

С помощью АппОптима.modifyUserAction вы можете изменить текущее действие пользователя. Вы можете изменить имя действия пользователя и сообщить о событиях, значениях и ошибках. Вы также можете отменить действие пользователя.

Доступны следующие операции для возвращаемого объекта пользовательского действия:

  • getName
  • setName
  • reportEvent
  • reportValue
  • reportError
  • cancelAction / cancel (ЕдиныйАгент for iOS version 8.241+)

Вы можете изменять пользовательское действие только до тех пор, пока оно не закрыто. Если пользовательское действие истекает до его изменения, изменение не будет иметь эффекта. Вызов метода leave на этом объекте также не будет иметь эффекта.

Swift Objective-C
UIButton *button;

[button dtxCustomControlName:@"Custom button title"];

UIButton *tableCell;

[tableCell dtxCustomCellName:@"Custom table cell title"];

UIButton *collectionCell;

[collectionCell dtxCustomCellName:@"Custom collection cell title"];@IBAction func buttonTouchUp(_ sender: Any) {

//for example, handle button touch, get values that should be put into user action name

//fetch current autogenerated action and modify it

АппОптима.modifyUserAction( { (action) -> () in

let oldName = action?.getName()

action?.setName("This is a renamed auto user action (was '\(oldName)')")

action?.reportValue(withName: "The Answer to the Ultimate Question of Life, the Universe, and Everything", intValue: 42)

action?.reportValue(withName: "G-force", doubleValue: 9.81)

action?.reportValue(withName: "Palindrome", stringValue: "Was it a car or a cat I saw?")

action?.reportError(withName: "Some error", errorValue: -1)

//other reportError also possible, skipping in this example

})

}

- (IBAction)buttontouchUp:(UIButton *)sender {

//for example, handle button touch, get values that should be put into user action name

//fetch current autogenerated action and modify it

[АппОптима modifyUserAction:^(DTXAction * _Nullable modifiableAction) {

NSString* oldName = [modifiableAction getName];

[modifiableAction setName:[NSString stringWithFormat: @"This is a renamed auto user action (was '%@')", oldName]];

[modifiableAction reportValueWithName: @"The Answer to the Ultimate Question of Life, the Universe, and Everything" intValue: 42];

[modifiableAction reportValueWithName: @"G-force" doubleValue: 9.81];

[modifiableAction reportValueWithName: @"Palindrome" stringValue: @"Was it a car or a cat I saw?"];

[modifiableAction reportErrorWithName: @"Some error" errorValue: -1];

//other reportError also possible, skipping in this example

}];

}


Максимальная длина имени для мобильного пользовательского действия (mobile custom action) или мобильного автоматически созданного пользовательского действия (mobile autogenerated user action) составляет 250 символов.

12.2. Изменить любое действие пользователя

ЕдиныйАгент для iOS версии 8.241+

Вы можете изменить автоматически сгенерированные действия пользователя с помощью АппОптима.modifyUserAction. Однако вы можете сделать это только для определенного действия пользователя, и обычно вы должны знать, открыто ли это действие пользователя или нет.

Чтобы преодолеть эти ограничения, мы представили функцию, которая позволяет вам получать обратный вызов (callback) для каждого вновь созданного действия пользователя. При таком подходе вы получаете уведомление о каждом новом автоматически сгенерированном действии пользователя, поэтому у вас есть возможность обновить имя действия пользователя, а также сообщить о событиях, значениях и ошибках. Вы также можете отменить действие пользователя.

Вы можете зарегистрировать обратный вызов, который вызывается для каждого автоматически сгенерированного действия пользователя. Вы можете установить обратный вызов в любом месте приложения в любой момент времени.

Важно

Любой ранее зарегистрированный обратный вызов перезаписывается последующим вызовом метода API.


Разрешены следующие операции:

  • getName
  • setName
  • reportEvent
  • reportValue
  • reportError
  • cancelAction / cancel
Swift Objective-C
АппОптима.setAutoUserActionCreationCallback { modifiableAction in

guard let modifiableAction = modifiableAction else {

return

}

if modifiableAction.getName().starts(with: "Loading") {

modifiableAction.cancel()

} else {

modifiableAction.setName("Modified Action: " + modifiableAction.getName())

}

}

[АппОптима setAutoUserActionCreationCallback:^(DTXAction * _Nullable modifiableAction) {

if (!modifiableAction) {

return;

}

if ([[modifiableAction getName] hasPrefix:@"Loading"]) {

[modifiableAction cancelAction];

} else {

[modifiableAction setName:[NSString stringWithFormat:@"Modified Action: %@", [modifiableAction getName]]];

}

}];


Максимальная длина имени для мобильных пользовательских действий или мобильных автогенерированных пользовательских действий составляет 250 символов.

13. Маскирование пользовательских действий

ЕдиныйАгент для iOS версии 8.249+

По умолчанию имена действий пользователя получаются из заголовков элементов пользовательского интерфейса, например, заголовков кнопок или ячеек таблицы. В редких случаях адреса электронной почты, имена пользователей или другая личная информация могут быть непреднамеренно включены в имена действий пользователя. Это происходит, когда эта информация включена в параметры, используемые для заголовков элементов управления, что приводит к именам действий пользователя, таким как Touch on Account 123456.

Если в названиях действий пользователей вашего приложения содержится такая личная информация, как имена или адреса, включите механизм маскирования действий пользователей. ЕдиныйАгент будет заменять все названия действий Touch on <control title> на тип элемента управления, к которому пользователь коснулся, например:

  • Touch on Account 123456 > Touch on Button
  • Touch on Transfer all amount > Touch on Switch
  • Touch on Country > Touch on TableCell

Чтобы включить маскирование действий пользователей, установите ключ конфигурации DTXUIActionNamePrivacy в true в файле Info.plist вашего приложения.

<key>DTXUIActionNamePrivacy</key>

<true/>


Маскирование пользовательских действий (user action masking) не изменяет пользовательские заголовки элементов управления (custom control titles).

Если вы хотите изменить названия только для определенных элементов управления или определенных действий пользователя, используйте одну из следующих настроек:

Содержание