All Products
Search
Document Center

Quick Tracking:HTTP API

Last Updated:Mar 31, 2025

Obtain server tracking parameters

  1. Go to the management console --> Click track Information

  2. Primary domain: the address for reporting server-side tracking data

  3. Secondary domain: The default domain is the same as the primary domain. Private deployment customers can provide secondary domains as alternate domains.

  4. The ServiceSecret and ServiceID are verification parameters. Do not disclose the secret.

Note: Because the above information involves system security, it can only be seen with administrator rights!

image.png

Request

API address: https://<Data collection endpoint + Port>/server

request parameters content-type:application/json

Request parameters

Report event request JSON parameters

JSON field name

(The upper and lower case must be consistent.)

Data type

Required

The field description.

Examples

sign

string

Yes

Verify the signature

f564cae6a8ad458648id9d607a124322

app_id

string

Yes

serviceID in the corresponding server tracking

OA8kI9Jis7YJNh5uh

appkey

string

Yes

Application key, obtained from QT management background

9moqdsuia8hvxm7k8shf82n

id

string

Yes

Event encoding, the encoding set by the user when creating an event in the QT background

click

umid

string

At least one of the two must be uploaded. We recommend that you upload the puid as much as possible to ensure that the IDMapping during analysis meets business requirements.

The device ID.

djajdjdk1

puid

string

The user ID.

user_001

page_name

string

No

Page name

page_index

ts

string

Yes

The timestamp that is reported in milliseconds.

1659493170125

cusp

object

No

Parameters

{"foo": "bar"}

gp

object

No

Global Properties

{"foo": "bar"}

sdk_type

string

Yes

The SDK type. The static field is httpapi.

httpapi

server_ts

string

No, the QT server can automatically generate it. If you manually upload a file, the time when the file is uploaded to the QT server prevails. The time when the file is uploaded to the QT server is no longer automatically generated.

Server timestamp in milliseconds

1659493170125

uuid

string

No. The factor used to generate the log_id (supported by V2.4.17)

If you want the log_id to be unique, you can report a unique UUID for each log entry. The QT server uses the UUID to generate the log_id.

1234567890

log_id

string

No, the QT server automatically generates

The log identifier. The default generation mode is uuid generation. If the uuid is not reported, a timestamp is used to generate a random id.

1234567890

Event Protocol

{ 
  "sign":"27 c95768438645138cfb010ded871091", // Required. The signature.

  
  "app_id":"xxxxxxxxx", // The service ID in the server tracking information.
  
  "appkey":"1344444", // Required. The appkey of the application.
  "id" : "get_coupons", // Required. The event code.
  "umid" : "edfafs", // The ID of the device.
  "puid" : "123456", // The ID of the logon user.
                                              // You must upload at least one of the umid and puid.
    
  "page_name":"home_page", // Optional. The page encoding. 
  "ts" : "1614667799165", // Required. The timestamp when the event occurred.
  "cusp" : { // Custom event parameters
    "p1" : "1",
    "p2" : "2",
    "p3" : "3"
  },
  
  "sdk_type":"httpapi", // static field. The tracking service automatically adds this field.
  "server_ts":"1614667799165", // If you specify this parameter, the value of the parameter is used. If you do not specify this parameter, the timestamp of the log tracking service is automatically used. The log tracking service automatically adds this parameter.
  "_id":'123344' // The unique code of the log. The tracking service automatically adds this field.
}

Report user property request JSON parameters

JSON field name

(The upper and lower case must be consistent.)

Data type

Required

The field description.

Examples

sign

string

Yes

Verify the signature

f564cae6a8ad458648id9d607a124322

app_id

string

Yes

serviceID in the corresponding server tracking

OA8kI9Jis7YJNh5uh

appkey

string

Yes

Application key, obtained from QT management background

9moqdsuia8hvxm7k8shf82n

id

string

Yes

The event code for reporting user attributes. The value is fixed as $$_ user_profile.

$$_user_profile

umid

string

No

The device ID.

djajdjdk1

puid

string

Yes

The user ID.

user_001

ts

string

Yes

The timestamp that is reported in milliseconds.

1659493170125

cusp

object

Yes

The user attribute.

{"name": "tom", "gender": "1"}

sdk_type

string

Yes

The SDK type. The static field is httpapi.

httpapi

server_ts

string

No, the QT server can automatically generate it. If you manually upload a file, the time when the file is uploaded to the QT server prevails. The time when the file is uploaded to the QT server is no longer automatically generated.

Server timestamp in milliseconds

1659493170125

uuid

string

No. The factor used to generate the log_id (supported by V2.4.17)

If you want the log_id to be unique, you can report a unique UUID for each log entry. The QT server uses the UUID to generate the log_id.

1234567890

log_id

string

No, the QT server automatically generates

The log identifier. The default generation mode is uuid generation. If the uuid is not reported, a timestamp is used to generate a random id.

1234567890

User Attribute Message Protocol

{ 
  "sign":"27 c95768438645138cfb010ded871091", // Required. The signature.
  "app_id":"xxxxxxxxx", // Required. This parameter corresponds to the service ID in the server tag information.
  
  
  "appkey":"1344444", // Required. The appkey of the application.
  "id" : "$$_user_profile", // Required. The ID is a user attribute.
  "umid" : "edfafs", // Optional. The ID of the device.
  "puid" : "123456", // Required. The account ID of the logon user.
  "ts" : "1614667799165", // Required. The timestamp when the event occurred.
  "cusp" : { // Required. Custom user attributes
    "gender" : "1", // The gender.
    "birthday" : "1988-12-24" // Date of birth
  },
  
  
  "sdk_type" : "httpapi", // static field. The tracking service automatically adds this field.
  "server_ts":"1614667799165", // If you specify this parameter, the value of the parameter is used. If you do not specify this parameter, the timestamp of the log tracking service is automatically used. The log tracking service automatically adds this parameter.
  "_id":'123344' // The unique code of the log. The tracking service automatically adds this field.
}

Sign generation rule description

  1. First, encapsulate the keys and values of all request fields except the sign field into a map object

  2. To serialize this map object into a JSON string, the keys need to be sorted according to natural sorting, i.e. ascii code. java can use jsonobject. tojsonstring (mapobject, SerializerFeature. mapsortfield),(note: json needs to be compressed to remove spaces between fields, such as the following code block)

  3. Get serviceSecret

  4. sign = MD5 (JSON string generated after sorting + serviceSecret)

  5. Put the calculated sign into the original map object and serialize it into a JSON string, which is the final complete JSON request message.

sign verification flowchart

image

Response parameters

Response data content-type:application/json

The response JSON string contains two fields: code and message

code

message

Description

Httpapi_300_200

Report success

Success

Httpapi_300_101

Illegal signature

Signature verification failed. For more information, see Sign generation rules.

Httpapi_300_102

The reported data type is not in JSON format.

The data format request parameters is not in JSON format

Httpapi_300_103

Missing required fields

Check whether required parameters are omitted by referring to the request parameter table

Httpapi_300_104

The user attribute is missing a required field

Check whether required parameters are omitted by referring to the request parameter table

Httpapi_300_105

Invalid event ID

Incorrect event ID

Httpapi_300_106

Incorrect ak/sk

Java Demo Reference

package com.aliyun.app.quickaplus.mock.once_mock;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.aliyun.app.quickaplus.mock.util.MD5Util;
import okhttp3.*;
import java.io.IOException;
/**
* Server ApiDemo
*
* @author chengtao
*/
public class ServiceApiDemo {
    /**
    * Primary domain
    */
    private static final String API_URL = "*****";
    /**
    * Corresponds to the ServiceID in the server tracking information.
    */
    private static final String SERVICE_ID = "*******";
    /**
    * Corresponds to the ServiceSecret in the server tracking information.
    */
    private static final String SERVICE_SECRET = "*******";
    /**
    * Client logs
    */
    private static final OkHttpClient client = new OkHttpClient();
/**
* Main function
*
* @param args parameters
*/
    public static void main(String[] args) {
        String srcJsonString = getMockData();
        JSONObject json = JSON.parseObject(srcJsonString);
        // Add the service ID to the message.
        json.put("app_id",SERVICE_ID);
        // Add ts to the message.
        json.put("ts", String.valueOf(System.currentTimeMillis()));
        //Calculate the signature
        String sign = MD5Util.md5(JSONObject.toJSONString(json,
        SerializerFeature.MapSortField) + SERVICE_SECRET);
        json.put("sign", sign);
        String desJsonString = JSON.toJSONString(json,
        SerializerFeature.DisableCircularReferenceDetect);
        Request request = new Request.Builder()
        .url(API_URL + "/server")
        .post(RequestBody.create(desJsonString,
        MediaType.parse("application/json")))
        .build();
        try {
            Response response = client.newCall(request).execute();
            if (!response.isSuccessful()) {
                System.out.printf("[DEMO] Failed to send log %s%n", response);
            } else {
                System.out.printf("[DEMO] Sent successfully %s%n",
                response.body().string());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
/**
* Obtain MockData.
*
* @return The return value.
*/
    private static String getMockData() {
        return "{\n" +
        " \"appkey\": \"1344444\",\n" +
        " \"id\": \"get_coupons\",\n" +
        " \"umid\": \"uuid()\",\n" +
        " \"puid\": \"puid1\",\n" +
        " \"page_name\": \"home_page\",\n" +
        " \"cusp\": {\n" +
        " \"p1\": \"1\",\n" +
        " \"p2\": \"2\",\n" +
        " \"p3\": \"3\"\n" +
        " },\n" +
        " \"gp\": {\n" +
        " \"p1\": \"1\",\n" +
        " \"p2\": \"2\",\n" +
        " \"p3\": \"3\"\n" +
        " },\n" +
        " \"sdk_type\": \"httpapi\"\n" +
        "}";
    }
}

Python Demo Reference

# The correct signature format.
{"appkey": "4b6G49PAkLUb4212","cusp":{"p1":"1","p2":"2","p3":"3"},"gp":{"p1":"1","p2":"2","p3":"3"},"id":"get_coupons","page_name":"home_page","puid":"puid1","sdk_type":"httpapi","umid":"uuid()"}tEkNnx8VDuR0mwEl3hXd7aozYh8Q2qS4
# The signature format is invalid.
{"appkey": "AppKey in your environment", "cusp": {"p1": "1", "p2": "2", "p3": "3"}, "gp": {"p1": "1", "p2": "2", "p3": "3"}, "id": "get_coupons", "page_name": "home_page", "puid": "puid1", "sdk_type": "httpapi", "umid": "uuid()"}tEkNnx8VDuR0mwEl3hXd7aozYh8Q2qS4 

import json
import hashlib
import http.client
import ssl
import time

# service_id
service_id =service_id in your environment
# service_secret
service_secret =service_secret in your environment
# Configure the tracking service.
qlc_end_point =address of the receiving service in your environment
# Message of Mock
def get_millisecond():
    # Obtain a 13-bit timestamp in milliseconds.
    millis = int(round(time.time() * 1000))
    return str(millis)
ts1 = get_millisecond()
print(ts1)
data = {
   # The code must be deleted when it is published. The code must be the same as the DebugKey that is entered in the "Tracking Verification-Server Verification"
     "dk":"",
   # Your appkey
    "appkey":"",
    "app_id": service_id,
    "id": "get_coupons",
    "umid": "uuid1",
    "puid": "puid2",
     "page_name": "home_page",
    "ts": ts1,
    "cusp": {
        "card_type": "self-managed",
        "scene": "Active purchase",
        "card_level": "Experience member",
        "carrier": "Enough apps",
        "card_no": "d7tyk",
        "user_id": "zsfMzsvHyA==",
        "card_name": "7-day experience card",
        "resource_id": "eedf17067cf64be299a844bbc8101426"
    },
    "gp": {
        "p1": "1",
        "p2": "2",
        "p3": "3"
    },
    "sdk_type": "httpapi"
}
def sort_dict(d):
    # The primary key of the sorted dictionary.
    sorted_dict = {k: sort_dict(v) if isinstance(v, dict) else v for k, v in sorted(d.items())}
    return sorted_dict
    
# Sort keys by lexicographic order.
sorted_data = sort_dict(data)
sorted_dict = dict(sorted_data)
#string = json.dumps(sorted_dict, separators=(',', ':')) + service_secret
string = json.dumps(sorted_dict,ensure_ascii=False, separators=(',', ':')) + service_secret
print(string)
data['sign'] = hashlib.md5(string.encode('utf-8')).hexdigest()
data = json.dumps(data)

protocl,domain = qlc_end_point.split('://')
if (protocl == 'http'):
    conn = http.client.HTTPConnection(domain)
if (protocl == 'https'):
    conn = http.client.HTTPSConnection(domain)
    
conn.request("POST", "/server", body=data, headers={"Content-Type": "application/json"})
response = conn.getresponse()
print(response.read().decode())
conn.close()

MD5Util class code

package com.aliyun.app.quickaplus.mock.util;

import java.security.MessageDigest;

/**
 * md5 encryption tool class
 *
 * @author zheng.zhang
 */
public class MD5Util {

    public static String md5(String s) {
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            byte[] btInput = s.getBytes();
            // Obtain the MessageDigest object of the MD5 digest algorithm.
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // Update the digest with the specified bytes
            mdInst.update(btInput);
            // Obtain the ciphertext.
            byte[] md = mdInst.digest();
            // Convert the ciphertext into a hexadecimal string.
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Unit testing
     */
    public static void main(String[] args) {
        StringBuilder dtskey = new StringBuilder("abc12390");
        dtskey.append('\0').append("~!@#$%^&*()_+");
        System.out.println(MD5Util.md5(dtskey.toString()));
        System.out.println(MD5Util.md5("20121221"));
        System.out.println(MD5Util.md5("Encryption"));
    }
}