1. How to view the instrumentation plan
Before you begin instrumentation, you must determine where to place tracking points and which events to track. This requires a clear and well-defined set of instrumentation requirements. The QuickTracking platform organizes these requirements into a standardized template called an instrumentation plan. An example is shown below.

An instrumentation plan specifies the following required information:
1. Event entity: This identifies who triggered the event. This can be a device ID or an account ID. Every reported event must include at least one of these identifiers.
Device ID: For Android and iOS devices, the default device ID is unique at the application level and is automatically generated by QuickTracking.
For devices running Android 9 and earlier, the SDK automatically collects the IMEI, Wi-Fi MAC address, Android ID, and serial number (SN) to generate a device ID. This ID is then stored locally. A new device ID is generated only when the user uninstalls the application or clears its data.
For devices running Android 10 and later, the SDK automatically collects the OAID, GAID, Android ID, and SN to generate a device ID. This ID is then stored locally. A new device ID is generated only when the user uninstalls the application or clears its data.
For iOS devices, the SDK automatically collects the OpenUDID to generate a device ID. This ID is then stored in the keychain. A new device ID is generated only when the user performs a factory reset or clears the application data.
The QuickTracking SDK collects the IDFA and OAID only if the application's end user consents to the collection. Only the QuickTracking app SDK can collect the OAID, GAID, IMEI, Wi-Fi MAC address, Android ID, SN, IDFA, and IDFV.
Account ID: This is the identifier for a user's account after they log on to the application. When a user logs on from different devices, the device ID changes, but the account ID remains the same. For example, a user might log on from both a mobile phone and a tablet.
2. User properties: These are properties associated with an account ID. For example, for a user with the account ID "testdemo@111", the "birthday" could be "1999-02-13" and the "membership level" could be "Platinum". In this case, "birthday" and "membership level" are user properties.
3. Channel properties: These are properties related to advertising campaigns, such as the advertising channel, delivery method, and ad content.
4. Global properties: These are properties that are set once globally and are then included with every event.
5. Page view events: These are events reported when a page loads. In the instrumentation plan, these are events where the page code and event code are the same, and they are marked in blue.
6. Click, exposure, and custom events: These are events reported whenever a user interacts with the application.
2. Set device ID & account ID
2.1 Set device ID
By default, the SDK collects the following parameters.
Device identifier or information | Collection method | Remarks |
idfa | [ASIdentifierManager advertisingIdentifier].UUIDString | Apple's advertising identifier |
idfv | [[UIDevice currentDevice].identifierForVendor UUIDString] | Application-level identifier |
openudid | [UIPasteboardpasteboardWithName:slotPBid create:NO] | openUdid (third-party) |
Taobao utdid | [UTDevice utdid] | QuickTracking collects this only if you have integrated the Taobao utdid SDK. |
mcc | [UMUtils mccString] | Mobile country code |
mnc | [UMUtils mncString] | Mobile Number |
device_model | [UMUtils deviceModelString] | Device model |
os_version | [UMUtils osVersionString] | OS version |
resolution | [UMUtils resolutionString] | Screen height and width |
If you want to control the collection behavior for some of the device identifiers in the table, for example, by not collecting them or by implementing your own collection method, you can provide a custom implementation in the corresponding block callback. If you return an empty value, the SDK will collect the identifier. The following code shows an example.
[QTConfigure customSetMncBlock:^NSString *{
return @"";
}];
[QTConfigure customSetDeviceModelBlock:^NSString *{
return @"custom-device-model";
}];
[QTConfigure customSetOSVersionBlock:^NSString *{
return @"custom-osversion";
}];
[QTConfigure customSetScreenResolutionBlock:^NSString *{
return @"2880*1308";
}];Note: Decide carefully whether to implement the corresponding method. If you choose to implement your own collection method, you are fully responsible for collecting the device identifier. The SDK will no longer attempt to collect it. The fewer device identifiers the SDK collects, the greater the negative impact on the accuracy and stability of your statistics.
// Before setting the data collection domain name and before calling the SDK pre-initializer function, call the collection utility registration function.
// If you do not need to control the device identifier collection behavior, you do not need to implement and register a custom utility class.
[QTConfigure customSetIdfvBlock:^NSString *{
return [[UIDevice currentDevice].identifierForVendor UUIDString];
}];
[QTConfigure setCustomDomain:@"Your data collection domain name" standbyDomain:nil];
[QTConfigure initWithAppKey:@"Your AppKey" channel:@"App Store"];The SDK supports custom device IDs. To use a custom device ID, you must call the `setCustomDeviceId:` interface with a valid (non-empty) value before initialization (before calling `init`).
+ (void)setCustomDeviceId:(NSString *)devID;Example:
[QTConfigure setCustomDeviceId:@"xxxxxx"];Note: This feature takes effect only when a device ID has not yet been retrieved. If a device ID already exists in local storage, this setting has no effect. To verify this feature when a local device ID exists, you must uninstall and reinstall the application.
2.2 Set account ID
1. QuickTracking (QT) uses the device as the standard for user statistics. To track accounts specific to your application, use the following interface:
Function:
+ (void)profileSignInWithPUID:(NSString *)puid;Parameters:
Parameter | Type | Description | Remarks |
puid | NSString | User account ID | Must be less than 64 bytes. |
Note: After an account ID is set, it is saved to local storage. The account ID becomes invalid only when the user uninstalls the app, clears the app data, or when you call the sign-off interface described below. Otherwise, every event will include the account ID.
Example:
[QTMobClick profileSignInWithPUID:@"UserID"];If you no longer need to bind the user account, you can call the sign-off interface. After this call, account-related information will no longer be sent.
+ (void)profileSignOff;Example:
[QTMobClick profileSignOff];2.3 Get device ID
Function:
+ (NSString *)umidString;Example:
NSString *deviceID = [QTConfigure umidString];3. Upload user properties
1. You can upload user properties using a custom event with the fixed event code `$$_user_profile`. The properties of this event are treated as user properties and stored in the user table.
NSDictionary *dict = @{@"sex" : @"girl", @"age" : @"8"};
[QTMobClick event:@"$$_user_profile" attributes:dict];Note: You must call the account tracking interface before you upload user properties.
4. Channel properties
After you set channel properties, all subsequent events automatically include them. These properties and their values are stored in the cache and are cleared when the app process ends. You can use these properties to view and filter data during analysis.
4.1 Launch the app from an H5 link
The URL Scheme used to launch the app must contain these channel properties. The property keys must start with `utm_` because `utm_` is the keyword that the SDK recognizes. For example: <URL scheme>?utm_channel=gzh
Add your URL Scheme to the project. The URL Scheme is located in Project Settings > Target > Info tab > URL Types. Enter the scheme. In `AppDelegate`, call the `[MobClick handleUrl:url]` function to receive the URL.
Call in AppDelegate:
- (BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url options:(nonnull NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
if ([QTMobClick handleUrl:url]) {
return YES;
}
return YES;
}Call in SceneDelegate:
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
for (UIOpenURLContext *context in connectionOptions.URLContexts) {
[QTMobClick handleUrl:context.URL];
}
}
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
[QTMobClick handleUrl:URLContexts.allObjects.firstObject.URL];
}Note: If your channel properties are already integrated with third-party advertising platforms and cannot start with `utm_`, you can use the global properties API to report the channel properties. However, the property keys must still start with `utm_`.
4.2 Launch the app marketplace from an H5 link to download and start the app
In this scenario, including `utm_` parameters in the H5 link is not sufficient to ensure the `utm_` parameters are included in the app launch event after download. Therefore, you must perform a fuzzy match between the H5 launch event and the app activation event based on the IP address and browser User-Agent.
When a user clicks the Launch/Download App button on the H5 page, you must report an app link event (`$$_app_link`). This event must include the AppKey of the app to be launched and the channel properties.
//Example
aplus_queue.push({
action:'aplus.recordAppLink',
arguments:[{
targetAppKey: 'AppKey of the app to launch', // Required. AppKey of the app to launch.
custom1: 'custom1', // Optional. Custom parameter.
...
}]
})The app install event (`$$_app_install`), which is the first launch event after the app is downloaded, is automatically collected and reported by the QT App SDK.
The QuickTracking system performs a fuzzy match between the app link event (`$$_app_link`) and the app install event (`$$_app_install`) based on the IP address and browser User-Agent. When you use this feature, you can directly analyze the channel properties of the App Activation (Preset) event in the app.
4.3 Statistics on active users from different app marketplaces
The second input parameter, `channel`, in the initializer function is used to set the app marketplace for the application: [QTConfigure initWithAppkey:@"Your AppKey" channel:@"App Store"];. In your analysis, you can view this information using System Properties > Upgrade Channel.
5. Global properties
After you register global properties, all subsequent events automatically include them. These properties and their values are stored in memory and are cleared when the app process ends. You can use these properties to view and filter data during analysis.
5.1 Register global properties
/**
* Set global properties as key-value pairs.
* If a key already exists as a global property, its value is updated.
* If a key does not exist as a global property, a new global property is inserted.
*/
+(void) registerGlobalProperty:(NSDictionary *)property;Parameter | Type | Description | Remarks |
property | NSDictionary | The names and values of the global properties. | - |
Data type description:
Data type | Example value | Data type recognized by the system after import | System limitations for this type |
NSNumber | @12 or @(12.0) | <Numeric: Integer, Long, Float, Short, Double> | None |
BOOL | @YES or @NO | <Boolean> | None |
NSString | "This is test Text" | <String> | Maximum length of 1024 bytes after UTF-8 encoding. The system discards the field if this limit is exceeded. |
NSArray | @[@"ABC", @"123"] | Collection List | By default, this is an array of string elements (duplicates are not removed). The maximum number of elements is 100. Each element has a maximum length of 255 bytes after UTF-8 encoding. |
NSDate |
| <Datetime> | We recommend using the first format, where SSS represents milliseconds.
|
Note:
Property names and property values of type `NSString` can contain only uppercase letters, lowercase letters, numbers, and underscores.
Property values can be one of the following types: `NSString`, `NSNumber`, `BOOL`, or `NSArray`.
If a key already exists as a global property, its value is updated. If a key does not exist, a new global property is inserted.
Example:
NSDictionary *firstPropertyDict = @{
@"a" : @"1",
@"b" : @"2",
@"testString" : @"abc",
@"testNumber" : @(12),
@"testTime" : [NSDate now],
@"testTime1" : @"2025-09-26",
@"testTime2" : @"2025-09-26 10:57:05",
@"testTime3" : @"2023-10-25 12:34:56.789",
@"testBool" : @YES,
@"testBool1" : @NO,
@"groupTest" : @[@"abc",@"2025-09-26", @YES]
};
// The current global properties are a:1, b:2, etc.
[QTMobClick registerGlobalProperty:firstPropertyDict];
NSDictionary *secondPropertyDict = @{
@"b" : @"3",
@"c" : @"4"
@"testString" : @"abc",
@"testNumber" : @(12),
@"testTime" : [NSDate now],
@"testTime1" : @"2025-09-26",
@"testTime2" : @"2025-09-26 10:57:05",
@"testTime3" : @"2023-10-25 12:34:56.789",
@"testBool" : @YES,
@"testBool1" : @NO,
@"groupTest" : @[@"abc",@"2025-09-26", @YES]
};
// The current global properties are a:1, b:3, c:4, etc.
[QTMobClick registerGlobalProperty:secondPropertyDict];5.2 Get a global property
/**
* Get a global property. Returns empty if it does not exist.
*/
+(NSString *) getGlobalProperty:(NSString *)propertyName;Parameter | Type | Description | Remarks |
propertyName | NSString | Property name. Can only contain uppercase letters, lowercase letters, numbers, and underscores. | - |
Return value | NSString | - |
5.3 Delete a global property
Deletes a specific global property. After deletion, subsequent events no longer include this property.
/**
*
* Delete the specified global property.
@param key
*/
+(void) unregisterGlobalProperty:(NSString *)propertyName;Parameter | Type | Description | Remarks |
propertyName | NSString | Property name. Can only contain uppercase letters, lowercase letters, numbers, and underscores. | - |
5.4 Get all global properties
/**
* Get all global properties. Returns empty if none exist.
*/
+(NSDictionary *)getGlobalProperties;Parameter | Type | Description | Remarks |
Return value | NSDictionary | The returned global property values are of type string and must be consistent with the parameter types passed when registering the global properties. | - |
5.5 Clear all global properties
/**
* Clear all global properties.
*/
+(void)clearGlobalProperties;6. Page view event API
The SDK provides two ways to report page view events: automatic page tracking and manual page tracking. You can also use both methods together.
6.1 Automatic page tracking
Automatic page tracking is implemented by hooking the system's `viewWillAppear` and `viewWillDisappear` methods to retrieve the class name. The SDK does not enable automatic page tracking by default. To enable it, you must call the interface before initialization.
Function:
+ (void)setAutoPageEnabled:(BOOL)value;Parameter | Type | Description | Remarks |
value | BOOL | Specifies whether to enable automatic page tracking. |
|
Example:
//Enable automatic page tracking
[QTMobClick setAutoPageEnabled:YES];6.1.1 Disable automatic reporting for a single page
If you have globally enabled automatic page tracking, you can use this interface to skip automatic tracking for a single page. Call this at the beginning of `viewWillAppear`. To skip tracking for only the current automatic page view, set the `pageName` parameter to `nil`.
Function:
+ (void)skipMe:(id)PageObject pageName:(NSString *)pageName;Example:
#import <QTCommon/UMSpmHybrid.h>
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//Do not track the current class for automatic page views
[UMSpmHybrid skipMe:[self class] pageName:nil];
}6.2 Manual page tracking
Function:
/** Automatic page duration tracking. Start recording the display duration of a page.
How to use: You must call beginLogPageView: and endLogPageView: in pairs to complete automatic tracking. Calling only one of these functions will not generate valid data.
Call beginLogPageView: when the page is displayed, and call endLogPageView: when you exit the page.
@param pageName The name of the page to track.
@return void.
*/
+ (void)beginLogPageView:(NSString *)pageName;
/** Automatic page duration tracking. Stop recording the display duration of a page.
How to use: You must call beginLogPageView: and endLogPageView: in pairs to complete automatic tracking. Calling only one of these functions will not generate valid data.
Call beginLogPageView: when the page is displayed, and call endLogPageView: when you exit the page.
@param pageName The name of the page to track.
@return void.
*/
+ (void)endLogPageView:(NSString *)pageName;Parameters:
Parameter | Type | Description | Remarks |
pageName | NSString | Statistics page encoding | The value must be the same for both `beginLogPageView` and `endLogPageView`. |
Note:
You must call `beginLogPageView:` and `endLogPageView:` in pairs to complete page tracking. If you call only one of these functions, valid data will not be generated.
Call `beginLogPageView:` when the page is displayed, and call `endLogPageView:` when you exit the page.
Example:
Call the following methods in pairs in the `viewWillAppear:` and `viewWillDisappear:` methods of your ViewController class:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[QTMobClick beginLogPageView:@"Pagename"]; //("Pagename" is the page name, which you can customize)
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[QTMobClick endLogPageView:@"Pagename"];
}You can also call `beginLogPageView:` and `endLogPageView:` in pairs in methods such as `viewDidAppear:` and `viewDidDisappear:` to complete page tracking based on your business scenario.
6.2.1 Set page properties
The `updatePageProperties` interface for iOS lets you attach custom properties to the current page. Interface:
/**
* @brief Update page business parameters.
*
* @param pageName Page name, such as Page_Detail.
* @param pProperties Business parameters, as key-value pairs.
*
* @warning How to call: Must be called before viewWillDisappear.
*
* Best practice: Call before viewWillDisappear.
*/
+(void) updatePageProperties:(NSString *)pageName properties:(NSDictionary *) pProperties;Parameters:
Parameter | Type | Description | Remarks |
pageName | NSString | Page code, such as Page_Detail. | |
pProperties | NSDictionary | Business parameters, as key-value pairs. |
Note: You must set page properties after you call `beginLogPageView`.
Import header file:
#import <QTCommon/UMSpm.h>Example:
[UMSpm updatePageProperties:@"page_home" properties: @{@"page_home_key":@"page_home_val"}];Note: Setting page properties is only supported for manual page instrumentation.
6.2.2 Pass-through page properties
In addition, the QuickTracking SDK provides the `updateNextPageProperties` interface for pass-through page property instrumentation, which lets you attach custom properties to the next page.
/**
* @brief Update business parameters for the next page.
*
* @param properties Business parameters to pass to the next page, as key-value pairs.
*
* @warning How to call: Must be called before the next page's pageAppear, otherwise it will carry incorrect data.
*
* Best practice: Call before the next page's pageAppear.
*/
+(void) updateNextPageProperties:(NSDictionary *) properties;Parameters:
Parameter | Type | Description | Remarks |
properties | NSDictionary | Business parameters to pass to the next page, as key-value pairs. |
Example:
You must call this before `beginLogPageView` is called for the next page.
[UMSpm updateNextPageProperties:@{@"news_next_key":@"news_next_val"}];Note: Pass-through page properties are only supported for manual page instrumentation.
7. Event instrumentation
You can use custom events to track user behavior and record the specific details of their actions.
7.1 Event instrumentation
Interface:
+ (void)event:(NSString *)eventCode;
+ (void)event:(NSString *)eventCode attributes:(NSDictionary *)attributes;
+ (void)event:(NSString *)eventId pageName:(NSString *)pageName attributes:(NSDictionary *)attributes;Parameter description:
Parameter | Type | Description | Remarks |
eventCode | NSString | Event code | The event code for a click, exposure, or custom event in the instrumentation plan. |
attributes | NSDictionary | Custom properties | - The value for a key in the properties cannot be empty. - The value can only be of type NSNumber, BOOL, NSString, or NSArray (elements in the array must be of type String). |
pageName | NSString | Page code | The page where the event occurs. This is the page code for the click, exposure, or custom event in the instrumentation plan. |
Event upload limits:
Maximum length of a custom property key string: 1024
Maximum length of a custom property value string: 1024 × 4
Maximum number of custom properties: 100 key-value pairs
Maximum length of a custom property array: 100 elements
Total length limit for a single log message: 2 MB
Data type description:
Data type | Example value | Data type recognized by the system after import | System limitations for this type |
NSNumber | @12 or @(12.0) | <Numeric: Integer, Long, Float, Short, Double> | None |
BOOL | @YES or @NO | <Boolean> | None |
NSString | "This is test Text" | <String> | Maximum length of 1024 bytes after UTF-8 encoding. The system discards the field if this limit is exceeded. |
NSArray | @[@"ABC", @"123"] | <Collection List> | By default, this is an array of string elements (duplicates are not removed). The maximum number of elements is 100. Each element has a maximum length of 255 bytes after UTF-8 encoding. |
NSDate |
| <Date and time> | We recommend using the first format, where SSS represents milliseconds.
|
Example 1:
To count the number of times the Forward event occurs in the application, call the following code in the forward function:
[QTMobClick event:@"Forward"];Example 2:
To count purchase events and track the type and quantity of purchased items, call the following code in the purchase function:
NSDictionary *dict = @{@"type" : @"book", @"quantity" : @"3"};
[QTMobClick event:@"purchase" attributes:dict];Example 3:
NSDictionary *dict = @{@"type" : @"book", @"quantity" : @"3"};
[QTMobClick event:@"purchase" pageName:@"ViewController" attributes:dict];Example 4:
NSDictionary *dict = @{
@"testString" : @"abc",
@"testNumber" : @(12),
@"testTime" : [NSDate now],
@"testTime1" : @"2025-09-26",
@"testTime2" : @"2025-09-26 10:57:05",
@"testTime3" : @"2023-10-25 12:34:56.789",
@"testBool" : @YES,
@"testBool1" : @NO,
@"groupTest" : @[@"abc",@"2025-09-26", @YES]
};
[QTMobClick event:@"purchase" attributes:dict];7.2 Duration events
SDK version 1.8.6.PX and later introduces duration events. These events let you manually control the lifecycle of a timer, including start, pause, resume, and end. The SDK automatically calculates the effective duration by excluding any paused time and supports reporting custom properties.
Interface:
/**
Start event timer.
@discussion
To track the duration of an event, first call eventTimerStart:"Event" at the start of the event to record the start time. This method does not actually send the event.
Then, at the end of the event, call eventTimerEnd: to report the data.
The time unit is milliseconds.
@param eventName The event name. Cannot be empty or nil.
@return Returns an eventId for subsequent pause, resume, or end timer operations.
*/
+ (NSString *_Nonnull)eventTimerStart:(NSString *_Nonnull)eventName;
/**
Set custom properties for a timed event.
@discussion
Set custom properties for a specified timed event. These properties will be included when the event is reported at the end.
This must be called after eventTimerStart: to be effective.
@param eventId The eventId of the event. Must match the eventId returned by eventTimerStart:.
@param propertyDict A dictionary of custom properties. Can be nil.
*/
+ (void)setTimer:(NSString *_Nonnull)eventId withProperties:(nullable NSDictionary *)propertyDict;
/**
Pause event timer.
@discussion
Pause the timer for a specified event. You can pause and resume the timer multiple times, and the time will be accumulated.
If eventTimerPause: is called multiple times, only the first call is effective. Subsequent calls are ignored.
@param eventId The eventId of the event. Must match the eventId returned by eventTimerStart:.
*/
+ (void)eventTimerPause:(NSString *_Nonnull)eventId;
/**
Resume event timer.
@discussion
Resume the timer for a paused event to continue accumulating the event duration.
If eventTimerResume: is called multiple times, only the first call is effective. Subsequent calls are ignored.
@param eventId The eventId of the event. Must match the eventId returned by eventTimerStart:.
*/
+ (void)eventTimerResume:(NSString *_Nonnull)eventId;
/**
End event timer.
@discussion
End the timer for a specified event and report the data. The reported data includes the event name and the accumulated duration.
If eventTimerEnd: is called multiple times, only the first call is effective. Subsequent calls are ignored.
@param eventId The eventId of the event. Must match the eventId returned by eventTimerStart:.
*/
+ (void)eventTimerEnd:(NSString *_Nonnull)eventId;7.2.1 Start timer (eventTimerStart)
Call this method when the event starts. This method generates a unique ID and starts a background task to save the timer.
Parameter | Type | Meaning |
event | NSString | The ID of the event being tracked. |
NSString (return value) | NSString | This method generates a unique ID. |
Example:
@property (nullable, copy) NSString *video_id;
self.video_id = [QTMobClick eventTimerStart:@"watch_video"];7.2.2 Set properties (setTimerProperties)
Use this method to associate metadata with the event, such as a title, URL, or type. You can call this method at any time after the event starts and before it ends.
Parameter | Meaning |
event | The unique ID returned for the current event. |
propertyDict | For event properties, see the content below. |
Event upload limits:
Maximum length of a custom property key string: 1024
Maximum length of a custom property value string: 1024 × 4
Maximum number of custom properties: 100 key-value pairs
Maximum length of a custom property array: 100 elements
Data type description:
Data type | Example value | Data type recognized by the system after import | System limitations for this type |
NSNumber | @12 or @(12.0) | <Numeric: Integer, Long, Float, Short, Double> | None |
BOOL | @YES or @NO | <Boolean> | None |
NSString | "This is test Text" | <String> | Maximum length of 1024 bytes after UTF-8 encoding. The system discards the field if this limit is exceeded. |
NSArray | @[@"ABC", @"123"] | Collection List | By default, this is an array of string elements (duplicates are not removed). The maximum number of elements is 100. Each element has a maximum length of 255 bytes after UTF-8 encoding. |
NSDate |
| <Datetime> | We recommend using the first format, where SSS represents milliseconds.
|
Example:
NSDictionary *dic = @{
@"video_id":@"10086",
@"category":@"movie",
@"video_title":@"Movie"
};
[QTMobClick setTimer:self.video_id withProperties:dic];7.2.3 Pause timer (eventTimerPause)
Call this method when the user pauses a video or when the video is buffering. If this method is called multiple times, only the first call is effective. Repeated calls do not accumulate additional pause time.
Parameter | Type | Meaning |
event | NSString | The unique ID returned for the current event. |
Example:
[QTMobClick eventTimerPause:self.video_id];7.2.4 Resume timer (eventTimerResume)
Call this method when the user resumes playback or when buffering ends. If this method is called multiple times, only the first call is effective.
Parameter | Type | Meaning |
event | NSString | The unique ID returned for the current event. |
Example:
[QTMobClick eventTimerResume:self.video_id];7.2.5 End and report (eventTimerEnd)
Call this method when video playback ends, the user closes the page, or the user switches videos.
This method performs the following actions:
Calculates the final effective playback duration in milliseconds.
Builds the JSON-formatted data for reporting.
Triggers the reporting callback. You must implement this callback based on your instrumentation plan.
Clears the task from local storage and memory.
Parameter | Type | Meaning |
event | NSString | The unique ID returned for the current event. |
[QTMobClick eventTimerEnd:self.video_id];7.3.6 Set auto-save interval (setEventTimeInterval)
Configures the automatic save interval. The default is 15 s. The configurable range is 1 s to 300 s.
Parameter | Type | Meaning |
interval | NSInteger | Persistence duration (milliseconds) |
Interface:
/** Set the interval for saving event duration data.
@param interval Milliseconds. The default is 15 seconds.
*/
+ (void)setEventTimeInterval:(NSInteger)interval;Example:
[QTConfigure setEventTimeInterval:10 * 1000];8. Auto-instrumentation
8.1 Scope of auto-instrumentation
The SDK is compatible with iOS 8.0 and later.
8.2 Auto-instrumentation API description
8.2.1 Automatic page tracking interface
Automatic page tracking is implemented by hooking the system's `viewWillAppear` and `viewWillDisappear` methods to retrieve the class name. You must call this before initialization. This feature is disabled by default.
/** Set whether to automatically track pages. Default is NO (do not automatically track).
@param value Set to YES, and the QT SDK will automatically track page information.
*/
+ (void)setAutoPageEnabled:(BOOL)value;Example:
[QTMobClick setAutoPageEnabled:YES];
//Set the domain name
[QTConfigure setCustomDomain:@"Your data collection domain name" standbyDomain:nil];
//Initialize the AppKey
[QTConfigure initWithAppkey:@"Your AppKey" channel:@"App Store"];Disable automatic page tracking for a specific page
/**
* @brief Skip tracking for the current page.
*
* @param PageObject Container object (used for automatic page tracking, can be nil for manual).
* @param pageName Page name (used for manual page setting, can be nil for automatic).
* @warning Call this interface before setting the page. After calling, data for the set native page will not be sent.
*
*/
+ (void)skipMe:(id)PageObject pageName:(NSString *)pageName;Example:
[UMSpmHybrid skipMe:self pageName:nil];8.2.2 Enable auto-instrumentation for control clicks
The following events are collected automatically:
Hooking the system's `sendAction:to:from:forEvent:` to monitor control method execution.
Listening to `addGestureRecognizer:` to capture all click behaviors.
Hooking `tableView:didSelectRowAtIndexPath:` to support `tableView` click behaviors.
Hooking `collectionView:didSelectItemAtIndexPath:` to support `collectionView` click behaviors.
You must call this before initialization. This feature is disabled by default.
/** Set whether to automatically track click events. Default is NO (do not automatically track).
@param value Set to YES, and the QT SDK will automatically track click events.
*/
+ (void)setAutoEventEnabled:(BOOL)value;Example:
[QTMobClick setAutoEventEnabled:YES];
//Set the domain name
[QTConfigure setCustomDomain:@"Your data collection domain name" standbyDomain:nil];
//Initialize the AppKey
[QTConfigure initWithAppkey:@"Your AppKey" channel:@"App Store"];Supported controls:
Control name | Remarks |
UITableView | |
UICollectionView | |
UIImageView | Only if it has a UITapGestureRecognizer behavior. |
UILabel | Only if it has a UITapGestureRecognizer behavior. |
UIButton | |
UISwitch | |
UIStepper | |
UISegmentedControl | |
UISlider | |
UIPageControl | |
UITabBarItem | |
UIBarButtonItem |
Ignore click events for a specific container
/**
* @abstract
* Ignore clicks on a specific page.
*
* @param PageObject The corresponding container.
*/
+(void)ignorePageView:(id)PageObject;Example:
// This method can be called multiple times to ignore a collection of views.
[QTAutoTrack ignorePageView:self];Ignore automatic tracking of click events for a specific type of control
Use the `ignoreViewType` method to ignore automatic tracking of click events for a specific type of control.
/**
* @abstract
* Ignore clicks for a specific type.
*
* @param aClass The Class corresponding to the View.
*/
+(void)ignoreViewType:(Class)aclass;Example:
// This method can be called multiple times to ignore a collection of types.
[QTAutoTrack ignoreViewType:[UIButton class]];
[QTAutoTrack ignoreViewType:[UISwitch class]];Ignore automatic tracking of click events for a specific control
Use the `UMAnalyticsIgnoreView` method to ignore automatic tracking of click events for a specific control.
button.UMAnalyticsIgnoreView=YES;8.2.3 Set custom information for a page
Set a custom code for a page
Implement the `-(NSString *)getUMPageName` method to return a custom code.
-(NSString *)getUMPageName
{
return @"testPageCode";
}Set custom properties for a page
Implement the `-(NSDictionary *)getUMPageProperties` method to set custom properties for a page.
-(NSDictionary *)getUMPageProperties
{
return @{@"key1":@"val1",@"key2":@"val2"};
}Set referrer (page_referrer) information for a page
Implement the `-(NSString *) getUMScreenUrl` method to return custom referrer information.
- (NSString *)getUMScreenUrl {
return @"um//um/page";
}8.2.4 Set custom properties for control click events
Using this method, you can set custom properties for a specific control. You can set multiple key-value pairs. Both the key and the value must be of type string. The custom properties and values are included in the auto-instrumentation click event data for this control.
button.UMAnalyticsViewProperties=@{@"key11":@"val11"};Set an event code for a control
Using this method, you can set an event code for a specific control.
button.UMAnalyticsEventCode=@"abcd123";8.3 Exposure instrumentation
This feature is supported in SDK 1.7.0.PX and later. For more information, see the iOS SDK Update Log.
To use the automatic exposure instrumentation feature, you must manually enable it in the configuration items (disabled by default).
// Enable exposure tracking
[QTConfigure setAutoExposureEnabled:YES showMonitorVerboseLog:NO];You can also disable automatic exposure tracking when needed.
// Disable exposure tracking
[QTConfigure setAutoExposureEnabled:NO showMonitorVerboseLog:NO];Parameter description:
Parameter | Type | Remarks |
exposureEnabled | BOOL | Specifies whether to enable automatic exposure tracking. The default is NO, which disables element exposure listening. |
showMonitorVerboseLog | BOOL | Verbose log switch for element exposure listening. The default is NO. Use this to view changes in exposure timing. |
8.4.1 Exposure configuration items
#import <QTCommon/QTCommon.h>
// General exposure settings
QTExposureConfig *config = [[QTExposureConfig alloc] initWithVisibleAreaThreshold:0 exposureDurationThreshold:0 allowRepeatExposure:YES];
[QTConfigure setExposureConfig:config];`QTExposureConfig` is used for exposure configuration properties. Its parameters are described below:
Parameter | Type | Description |
visibleAreaThreshold | CGFloat | Minimum exposure ratio. The default value is 0.5f. The range is 0 to 1f.
|
exposureDurationThreshold | NSTimeInterval | Effective exposure duration. The minimum is 0.3. The default is 0.3. An exposure event is triggered only if the element is displayed for longer than this duration. |
allowRepeatExposure | BOOL | Specifies whether to allow repeat exposures. The default is YES.
|
8.4.1 Set global exposure configuration
Use the `setExposureConfig` method to set global exposure properties. You must call this method before you initialize the SDK.
#import <QTCommon/QTCommon.h>
[QTConfigure setExposureConfig:config];8.4.2 Mark elements for exposure
To use the exposure feature, you must manually bind the elements for exposure. You can call the `addViewForExposure` method to bind them.
//Add a view for exposure
+ (void)addViewForExposure:(UIView *_Nullable)view withData:(QTExposureData *_Nullable)data;Parameter description:
Parameter | Type | Remarks |
view | UIView | The view object for which to track exposure. |
data | QTExposureData | For details on exposure data, see the table below. |
QTExposureData API:
/// Encapsulates exposure event data, including event name, custom properties, exposure identifier, and exposure configuration.
@interface QTExposureData : NSObject
// Exposure configuration
@property (nonatomic, copy) QTExposureConfig *exposureConfig;
// Custom event properties
@property (nonatomic, strong) NSDictionary<NSString *, id> *properties;
// Event name
@property (nonatomic, copy) NSString *event;
// Unique identifier for the view
@property (nonatomic, copy, readonly) NSString *exposureIdentifier;
@property (nonatomic, weak) id<QTExposureListener> exposureListener;
// Initializer function
- (instancetype)initWithEvent:(NSString *)event properties:(NSDictionary<NSString *, id> *)properties exposureConfig:(QTExposureConfig *)exposureConfig exposureIdentifier:(NSString *)exposureIdentifier;
@endParameter description:
Parameter | Type | Description |
event | NSString | Event name (required) |
properties | NSDictionary<NSString *, id> | Exposure event properties (optional) |
exposureConfig | QTExposureConfig | Exposure configuration (optional, uses global configuration by default) |
exposureIdentifier | NSString | Unique identifier for the element |
Marking normal elements
Example:
#import <QTCommon/QTCommon.h>
// Construct exposure data
QTExposureData *data = [[QTExposureData alloc] initWithEvent:@"test_item_exp" properties:nil exposureConfig:nil exposureIdentifier:nil];
[QTMobClick addViewForExposure:view withData:data];Marking list-type elements
Mark all elements
#import <QTCommon/QTCommon.h>
QTExposureConfig *config = [[QTExposureConfig alloc] initWithVisibleAreaThreshold:0 exposureDurationThreshold:0 allowRepeatExposure:YES];
QTExposureData *data = [[QTExposureData alloc] initWithEvent:@"test_whole_tableview_exp" properties:@{
@"tableviewName":@"xxxx"
} exposureConfig:config exposureIdentifier:nil];
[QTMobClick addViewForExposure:self.tableView withData:data];Mark a single element:
Individual list elements are often reused, and their positions can change due to operations such as refresh, delete, or add. We recommend that you add the exposureIdentifier field to the exposure data and ensure that the ID is unique.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"exposureCell"];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 20)];
label.text = [NSString stringWithFormat:@"session:%ld", (long)indexPath.section];
[cell addSubview:label];
UILabel *label2 = [[UILabel alloc] initWithFrame:CGRectMake(160, 0, 100, 20)];
label2.text = [NSString stringWithFormat:@"row:%ld", (long)indexPath.row];
[cell addSubview:label2];
QTExposureData *data;
// Define the event code for the exposure event
NSString *cell_exp_eventcode = [NSString stringWithFormat:@"exposure_cell_%ld_%ld", indexPath.section, (long)indexPath.row];
// Define the property dictionary for the element to be exposed
NSDictionary *properties = @{ @"cell_image_name": @"xxxx" };
// Define the unique identifier for the exposed element
NSString* uniqueExpItemId = @"xxxx";
// Define the exposure timing control for a single list element
// By default, the element is in the viewport for more than 50% of its area and for 300ms
// Customize whether repeat exposure is needed as needed
QTExposureConfig* expItemConfig = [[QTExposureConfig alloc] initWithVisibleRadio:0.5 exposureMinDuration:0.3 allowRepeatExposure:YES];
//Assemble the exposure data
data = [[QTExposureData alloc] initWithEvent:cell_exp_eventcode
properties:properties
exposureConfig:expItemConfig
exposureIdentifier:uniqueExpItemId];
/* Other optional exposure data configuration APIs
data = [[QTExposureData alloc] initWithEvent:cell_exp_eventcode
properties:properties];
data = [[QTExposureData alloc] initWithEvent:cell_exp_eventcode
exposureConfig:expItemConfig
exposureIdentifier:uniqueExpItemId];
data = [[QTExposureData alloc] initWithEvent:cell_exp_eventcode
properties:properties
exposureIdentifier:uniqueExpItemId];
data = [[QTExposureData alloc] initWithEvent:cell_exp_eventcode
properties:properties
exposureConfig:expItemConfig];
*/
[QTMobClick addViewForExposure:cell withData:data];
return cell;
}8.4.3 Remove elements from exposure tracking
When an element is removed, the corresponding instrumentation monitoring is also removed. For example, this occurs when a list is deleted.
You can also use `removeViewForExposure` to remove elements that no longer need exposure tracking.
[QTMobClick removeViewForExposure:view withExposureIdentifier:nil];9. Viral sharing
Viral sharing is a key concept in growth hacking strategies. It relies on social connections between users to spread information, thereby promoting new user acquisition.
After you integrate the viral sharing feature of the SDK, you can use the sharing trend model in the QuickTracking platform to measure the effectiveness of your marketing campaigns in acquiring new users through sharing and referral metrics.
View the top sharing users and the referral effectiveness metrics for different referral levels.
Flexibly configure and combine referral metrics to identify top users with the strongest viral acquisition and referral conversion capabilities. You can track user sharing links and referral relationships to quickly locate key opinion consumers.
9.1 Get source sharing parameters
/*
* Get source sharing parameters API
* return @{ @"$$_ref_share_id": @"xxxxx", @"$$_ref_share_url": @"xxxxx"}
**/
+(nullable NSDictionary *)getRefShareParams;Version requirements
iOS SDK v1.5.0.PX and later.
Feature
When a referred user opens the app, this API is used to retrieve the source share ID and source share URL.
Request parameter
None
Return value
Returns an empty dictionary `{}` by default. If values are present, it returns the following:
Parameter | Type | Default | Meaning | Remarks |
$$_ref_share_url | String | "" | The source share URL, excluding the share ID. | None |
$$_ref_share_id | String | "" | The source share ID. | None |
Example
-(void)onShare {
__weak typeof(self) weakSelf = self;
NSDictionary* refShareParams = [QTMobClick getRefShareParams];
NSString* $$_ref_share_id = [refShareParams objectForKey:@"$sid"];
[QTMobClick requestShareParams:@"https://www.lydaas.com/?utm_source=share" params:@{
@"title": @"This is a share title",
@"campaign":@"This is a share campaign",
@"shareId": $$_ref_share_id
} timeout:0 shareResultHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"result === %@", result);
if (error) {
NSLog(@"error === %@", error);
}
__block NSString *shareId = [(NSDictionary*)result objectForKey:@"$sid"];
NSDictionary *dict = @{
@"$$_share_id": shareId,
@"$$_share_url" : @"https://www.lydaas.com/?utm_source=share",
@"$$_share_title" : @"Share Campaign A",
@"$$_share_campaign_id" : @"This is a custom share campaign",
@"$$_share_type" : @"User-defined sharing platform"
};
[QTMobClick event:@"$$_share" attributes:dict];
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:@"Sharing Parameters" message:[NSString
stringWithFormat:@"Request for sharing parameters returned the following result:\n\n {\n $sid:%@ \n} \n", shareId]
preferredStyle:UIAlertControllerStyleAlert];
// Create UIAlertAction
UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"Got it"
style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
// Handle the click on the confirm button
NSLog(@"User has copied");
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = shareId;
}];
[alertController addAction:confirmAction];
[weakSelf presentViewController:alertController animated:YES completion:nil];
});
}];
}9.2 Request sharing parameters
#import <QTCommon/MobClick.h>
/*
* Get sharing parameters API
* @param url, The URL of the shared page. This is required.
* @param params Possible sharing parameters. Can be null.
* {
* @"title": Share title, //Can be null, max length 4*1024
* @"shareId": Source share ID, //Can be null
* @"campaign": Share campaign, //Can be null, max length 4*1024
* ... for future extension
* }
* @param timeout Request timeout in seconds. Valid range: 0-10 (inclusive). If 0 is passed, the SDK's internal default of 3 seconds is used.
* @param shareResultHandler The result callback object. This is required and cannot be null.
*/
+(void)requestShareParams:(nonnull NSString *)url
params:(nonnull NSDictionary *)params
timeout:(int)timeout
shareResultHandler:(nonnull QTShareResultHandler)shareResultHandler;Version requirements
iOS SDK v1.5.0.PX and later.
Feature
Requests the share ID that is required to build a sharing link.
Request parameter
Parameter | Type | Default | Meaning | Remarks |
url | NSString | nil | The URL of the shared page. | Required. Cannot be nil. |
params | NSDictionary | nil | Request parameters for the get sharing parameters API. |
campaign: Share campaign identifier. String type, default value is "", max length is 4 × 1024 characters. title: Share title. String type, default value is "", max length is 4 × 1024 characters. shareId: Source share ID. String type, default value is "". |
timeout | int | 0 | Interface timeout. | Value range is 1-10, in seconds. The SDK default timeout is 3 seconds. |
shareResultHandler | QTShareResultHandler | nil | The result callback object. | Required. Cannot be nil. Note: This result callback runs on the SDK's internal background network request thread. To manipulate UI controls in the callback method, execute the relevant operations on the UI thread handler. |
Return value
Parameter | Type | Default | Meaning | Remarks |
result | NSDictionary | nil | Result of the sharing parameters API request. | Contains a property Contains one property: `$sid`, of type NSString, which is the share ID. |
error | NSError | nil | Error from the sharing parameters API request. | None |
Example
-(void)onShare {
__weak typeof(self) * weakSelf = self;
[QTMobClick requestShareParams:@"https://www.lydaas.com/?utm_source=share"
params:@{
@"title": @"This is a share title",
@"campaign":@"This is a share campaign",
@"shareId": @"This is a share id"
}
timeout:0
shareResultHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"result === %@", result);
if (error) {
NSLog(@"error === %@", error);
}
__block NSString *shareId = [(NSDictionary*)result objectForKey:@"$sid"];
NSDictionary *dict = @{
@"$$_share_id": shareId,
@"$$_share_url" : @"https://www.lydaas.com/?utm_source=share",
@"$$_share_title" : @"Share Campaign A",
@"$$_share_campaign_id" : @"This is a custom share campaign",
@"$$_share_type" : @"User-defined sharing platform"
};
[QTMobClick event:@"$$_share" attributes:dict];
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Sharing Parameters"
message:[NSString stringWithFormat:
@"Request for sharing parameters returned the following result:\n\n {\n $sid:%@ \n} \n", shareId]
preferredStyle:UIAlertControllerStyleAlert];
// Create UIAlertAction
UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"Got it"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
// Handle the click on the confirm button
NSLog(@"User has copied");
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = shareId;
}];
[alertController addAction:confirmAction];
[weakSelf presentViewController:alertController animated:YES completion:nil];
});
}];
}9.3 Report sharing event
Report the sharing event using the preset event code $$_share.
Example:
[QTMobClick requestShareParams:@"https://www.lydaas.com/?utm_source=share"
params:@{
@"title": @"This is a share title",
@"campaign":@"This is a share campaign",
@"shareId": @"This is a share id"
}
timeout:0
shareResultHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"result === %@", result);
if (error) {
NSLog(@"error === %@", error);
}
__block NSString *shareId = [(NSDictionary*)result objectForKey:@"$sid"];
NSDictionary *dict = @{
@"$$_share_id": shareId,
@"$$_share_url" : @"https://www.lydaas.com/?utm_source=share",
@"$$_share_title" : @"Share Campaign A",
@"$$_share_campaign_id" : @"This is a custom share campaign",
@"$$_share_type" : @"User-defined sharing platform"
};
[QTMobClick event:@"$$_share" attributes:dict];
}];Note: The launched link must include the "$sid" parameter, where the value is the share ID. For example: `https://example.aliyun.com/path/to/content?$sid=123456`