others-Adjust第三方统计

本文详细介绍Adjust SDK的集成步骤,包括Gradle依赖配置、权限声明、混淆规则设定及Java代码实现。此外,还提供了自定义短链配置、Facebook Ads投放及API事件上报等实用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


title: others-Adjust第三方统计
categories: Others
tags: [others, Adjust, 统计]
date: 2020-09-21 14:13:14
comments: false
mathjax: true
toc: true

others-Adjust第三方统计


前篇

  • 官网 - https://www.adjust.com/
    • Android 集成文档: https://docs.adjust.com/zh/sdk/android/
    • 接入文档: https://github.com/adjust/android_sdk

接入

  1. build.gradle 引入库

    dependencies {
        implementation 'com.adjust.sdk:adjust-android:4.24.1'
        implementation 'com.google.android.gms:play-services-ads-identifier:17.0.0'
        implementation 'com.android.installreferrer:installreferrer:2.1'
    }
    
  2. 权限 及 广播 的 清单配置 AndroidManifest.xml

    <manifest>
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <!-- Optional : -->
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        
        <application>
    		<!-- adjust -->
            <receiver
                android:name="com.adjust.sdk.AdjustReferrerReceiver"
                android:permission="android.permission.INSTALL_PACKAGES"
                android:exported="true" >
                <intent-filter>
                    <action android:name="com.android.vending.INSTALL_REFERRER" />
                </intent-filter>
            </receiver>
        </application>
    </manifest>
    
  3. 混淆配置 proguard-user.txt

    ######### adjust #########
    -keep class com.adjust.sdk.** { *; }
    -keep class com.google.android.gms.common.ConnectionResult {
        int SUCCESS;
    }
    -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient {
        com.google.android.gms.ads.identifier.AdvertisingIdClient$Info getAdvertisingIdInfo(android.content.Context);
    }
    -keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info {
        java.lang.String getId();
        boolean isLimitAdTrackingEnabled();
    }
    -keep public class com.android.installreferrer.** { *; }
    
  4. java 代码

    package com.ecological.auctioneer.other;
    
    import android.app.Activity;
    import android.app.Application;
    import android.content.Context;
    import android.os.Bundle;
    import android.util.Log;
    
    import com.adjust.sdk.Adjust;
    import com.adjust.sdk.AdjustConfig;
    import com.adjust.sdk.AdjustEvent;
    import com.adjust.sdk.LogLevel;
    import com.ecological.auctioneer.Define;
    import com.ecological.auctioneer.JsonTool;
    import com.ecological.auctioneer.LogUtil;
    import com.ecological.auctioneer.MyCode.ECode;
    import com.ecological.auctioneer.SystemInfoUtil;
    import com.ecological.auctioneer.Tools;
    import com.ecological.auctioneer.model.JsonBean.CEventInfo;
    import com.ecological.auctioneer.model.JsonBean.CTransfer;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class AdjustHelper {
    
        static AdjustHelper instance = null;
    
        public static AdjustHelper getIns() {
            if (instance == null) {
                instance = new AdjustHelper();
            }
            return instance;
        }
    
        private static final String TAG = "--- AdjustHelper";
        private static final String ResKey_Token = "adjust_token";
        private static final String ResKey_Secret = "adjust_secret";
    
        private boolean mIsCall = false;
        private CTransfer mTransfer = new CTransfer(); // 保存数据
    
    //    // ---------------- 测试字段
    //    private String mAttribution = "attr: ";
    //    private String mEventTrackingSucceeded = "ets: ";
    //    private String mEventTrackingFailed = "etf: ";
    //    private String mSessionTrackingSucceeded = "sts: ";
    //    private String mSessionTrackingFailed = "stf: ";
    
    
        public void init(Activity activity, boolean isDebug, Define.TransferRunnable task) {
            if (isDebug) {
                Log.d(TAG, "AdjustHelper debug mode");
            }
    
            String token = Tools.GetStringVaule(activity, ResKey_Token);
            if (!Tools.isEmpty(token)) {
                // ad 回调
                initAdjust(activity, token, isDebug, (code, adJson) -> {
                    if (code != ECode.Ok) {
                        return;
                    }
    
                    mTransfer.AdJson = adJson;
                    LogUtil.TD(TAG, "--- initAdjust ok, AdJson: %s", mTransfer.AdJson);
                    callTask(task);
                });
    
                // referer 回调
                initReferer(activity, (code, msg) -> {
                    if (code != ECode.Ok) {
                        return;
                    }
    
                    mTransfer.GgJson = Tools.parseUrl2Json(msg);
                    LogUtil.TD(TAG, "--- initReferer ok 111, GgJson: %s", mTransfer.GgJson);
                    // callTask(task); 不能 callTask, 要等 onConversionDataSuccess 回调
                });
            } else {
                initReferer(activity, (code, msg) -> {
                    if (code != ECode.Ok) {
                        return;
                    }
    
                    mTransfer.GgJson = Tools.parseUrl2Json(msg);
                    LogUtil.TD(TAG, "--- initReferer ok 222, GgJson: %s", mTransfer.GgJson);
                    callTask(task);
                });
            }
        }
    
        private void initAdjust(Activity activity, String token, boolean isDebug, Define.CodeRunnable task) {
            String secret = Tools.GetStringVaule(activity, ResKey_Secret);
            List<Long> infoLst = parseSecret(secret);
    
            String environment = AdjustConfig.ENVIRONMENT_PRODUCTION;
            if (isDebug) {
                environment = AdjustConfig.ENVIRONMENT_SANDBOX;
            }
    
            AdjustConfig config = new AdjustConfig(activity, token, environment);
            config.setAppSecret(infoLst.get(0), infoLst.get(1), infoLst.get(2), infoLst.get(3), infoLst.get(4));
            config.setLogLevel(isDebug ? LogLevel.VERBOSE : LogLevel.ERROR); // disable warning logs
            config.setSendInBackground(true);
    
            // -------- 注册各种回调
            // Set attribution delegate.
            config.setOnAttributionChangedListener(attribution -> {
                LogUtil.TD(TAG, "Attribution: " + attribution.toString());
                task.run(ECode.Ok, JsonTool.toJson(attribution));
            });
    
            // Set event success tracking delegate.
            config.setOnEventTrackingSucceededListener(eventSuccessResponseData -> {
                LogUtil.TD(TAG, "Event success data: " + eventSuccessResponseData.toString());
            });
    
            // Set event failure tracking delegate.
            config.setOnEventTrackingFailedListener(eventFailureResponseData -> {
                LogUtil.TD(TAG, "Event failure data: " + eventFailureResponseData.toString());
            });
    
            // Set session success tracking delegate.
            config.setOnSessionTrackingSucceededListener(sessionSuccessResponseData -> {
                LogUtil.TD(TAG, "Session success data: " + sessionSuccessResponseData.toString());
            });
    
            // Set session failure tracking delegate.
            config.setOnSessionTrackingFailedListener(sessionFailureResponseData -> {
                LogUtil.TD(TAG, "Session failure data: " + sessionFailureResponseData.toString());
            });
    
            // Evaluate deferred deep link to be launched.
            config.setOnDeeplinkResponseListener(deeplink -> {
                LogUtil.TD(TAG, "Deep link URL: " + deeplink);
    
                return true;
            });
    
    
            Adjust.onCreate(config);
            activity.getApplication().registerActivityLifecycleCallbacks(new AdjustLifecycleCallbacks());
        }
    
        private void initReferer(Context context, Define.CodeRunnable task) {
            GoogleReferrerHelper.getIns().start(context, task);
        }
    
        public static List<Long> parseSecret(String secret) {
            List<Long> numLst = new ArrayList<>();
            try {
                String[] idArr = secret.split(",");
                for (String idStr : idArr) {
                    long num = Long.parseLong(idStr.trim());
                    numLst.add((num));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            LogUtil.TA(TAG, numLst.size() == 5, "--- parseSecret error, size: %d", numLst.size());
            return numLst;
        }
    
        private static final class AdjustLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    
            }
    
            @Override
            public void onActivityStarted(Activity activity) {
    
            }
    
            @Override
            public void onActivityResumed(Activity activity) {
                Adjust.onResume();
            }
    
            @Override
            public void onActivityPaused(Activity activity) {
                Adjust.onPause();
            }
    
            @Override
            public void onActivityStopped(Activity activity) {
    
            }
    
            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    
            }
    
            @Override
            public void onActivityDestroyed(Activity activity) {
    
            }
        }
    
        public void logEvent(String jsonMsg, Define.CodeRunnable task) {
            if (SystemInfoUtil.ThirdSdk != Define.EThirdSdk.Adjust) {
                return;
            }
    
            CEventInfo ei = JsonTool.toObject(jsonMsg, CEventInfo.class);
            logEvent(ei, task);
        }
    
        public void logEvent(CEventInfo ei, Define.CodeRunnable task) {
            if (ei == null || ei.name.length() == 0 || SystemInfoUtil.ThirdSdk != Define.EThirdSdk.Adjust) {
                return;
            }
    
            LogUtil.TD(TAG, "--- event: %s", JsonTool.beauty(ei));
    
            AdjustEvent adjustEvent = new AdjustEvent(ei.name);
            if (ei.valueToSum > 0.001f) {
                String curr = "INR";
                if (ei.params.size() > 0 && ei.params.containsKey("currency")) {
                    curr = (String) ei.params.get("currency");
                }
                adjustEvent.setRevenue(0.01, curr);
            }
            Adjust.trackEvent(adjustEvent);
        }
    
        public String getInfo() {
            return JsonTool.toJson(mTransfer);
        }
    
    //    public void showMsg(Context ctx) {
    //        CTips tps = new CTips();
    //        tps.msg = String.format("%s\n%s\n%s\n%s\n%s"
    //                , mAttribution, mEventTrackingSucceeded, mEventTrackingFailed, mSessionTrackingSucceeded, mSessionTrackingFailed);
    //        Tools.tips02(ctx, tps, null);
    //    }
    
    
        private void callTask(Define.TransferRunnable task) {
            if (mIsCall || task == null) {
                return;
            }
    
            mIsCall = true;
            task.run(mTransfer);
        }
    }
    

自定义短链配置 - 跟踪链接

Google Play 应用的短链推广

  1. 后台配置, 把需要透传的参数设置到 推广结构 中.

  2. adjust 回调中 可以获取到 归因数据 Addata

    {\"Addata\":\"{\\\"adgroup\\\":\\\"bbb\\\",\\\"adid\\\":\\\"a5ad874ca32aa310c636adaf54396ab6\\\",\\\"campaign\\\":\\\"aaa\\\",\\\"creative\\\":\\\"ccc\\\",\\\"network\\\":\\\"ad3\\\",\\\"trackerName\\\":\\\"ad3::aaa::bbb::ccc\\\",\\\"trackerToken\\\":\\\"3lcxp3p\\\"}\",\"Appid\":3,\"Deviceid\":\"1183eca72cbe5513eaf1e4f1232a8ee8\",\"Ggdata\":\"{\\\"utm_content\\\":\\\"bbb\\\",\\\"adjust_reftag\\\":\\\"cvmLwqpUXZUfr\\\",\\\"utm_term\\\":\\\"ccc\\\",\\\"utm_source\\\":\\\"ad3\\\",\\\"pid\\\":\\\"1109\\\",\\\"utm_campaign\\\":\\\"aaa\\\"}\
    

Facebook Ads 投放

需要 Facebook 对应的 app id 接收 服务条款, 才能在 af 的 onConversionDataSuccess 回调中, 接收到 campaign 相关数据

链接: https://www.facebook.com/ads/manage/advanced_mobile_measurement/app_based_tos?appid=123123 (123123 是 app id)

  • 合伙伙伴设置 中, 添加 facebook, 填入 fb app id.

    • 然后就可以在 adjust 的回调用获取到 fb 广告系列的名字

      config.setOnAttributionChangedListener(attribution -> { // adjust 归因回调
          LogUtil.TD(TAG, "Attribution: " + attribution.toString());
          task.run(ECode.Ok, JsonTool.toJson(attribution));
      });
      
      // 获取到的数据
      \"Addata\":\"{\\\"adgroup\\\":\\\"0918 (23845782953730115)\\\",\\\"adid\\\":\\\"eee\\\",\\\"campaign\\\":\\\"ln_1094_rum9.19\\\",\\\"creative\\\":\\\"1 (23845782953750115)\\\",\\\"network\\\":\\\"Facebook Installs\\\",\\\"trackerName\\\":\\\"Facebook Installs::ln_1094_rum9.18 (23845782953570115)::0918 (23845782953730115)::1 (23845782953750115)\\\",\\\"trackerToken\\\":\\\"ofkv4pp\\\"}\"
      
      • campaign 对应的就是 fb 广告系列名字


查看归因

  • 所有设置 -> 测试控制台, 输入 谷歌广告 id (gaid), 可以查看到该设备的 归因数据.


api 上报事件

官方文档: https://help.adjust.com/en/article/server-to-server-events

先确定是否归因正确 查看归因 , 再查看事件的归因是否正确.

  1. 生成 s2s 秘钥 secret. 所有设置 -> S2S 安全 -> 创建识别码, 如: b78a67xxxxxx

  2. 激活 s2s. 所有设置 -> S2S 安全 -> 激活 S2S 认证

  3. 上报参数中, 不用平台的使用 id 字段不同

    • Android: gps_adid, Google 广告 id, 通过 Adjust.getGoogleAdId 回调中获取到
    • ios: idfa
py 测试代码
  • 测试用例

    # adjust
    def test_adEvent(self):
        from urllib.parse import urlencode, quote
    
        appToken = "y0sxxx"
        eventToken = "4vexxx"
        secret = "b78a67xxxxxx"
        aduid = "ed6ec341-277c-43ce-b48d-xxx"
    
        params = {
            "revenue": 100,  # 收益
            "currency": "INR",  # 币种
            "environment": "production",  # 生成 or 测试环境
        }
    
        data = {
            "s2s": 1,
            "app_token": appToken,
            "event_token": eventToken,
            "gps_adid": aduid,  # 不同环境配置的值不一样, Android: gps_adid, 谷歌广告id
            "partner_params": quote(utils.beautyJson(params, indent=None)),  # 要 encode
        }
    
        url = "https://s2s.adjust.com/event?{}".format(urlencode(data, doseq=False))  # 不要 encode
        headers = {
            "Authorization": "Bearer {}".format(secret),
            "Content-Type": "application/json",
        }
    
        print("--- url: {}".format(url))
        code, rspDct = utils.httpPost(url, headers=headers)
        print("--- code: {}".format(code))
        print("--- rsp: {}".format(utils.beautyJson(rspDct)))
    
    • 上报成功, 返回的 json 有 "status": "OK" 才代表成功了.

      如果是 code: 200 但是 json 是空的, 则是上报失败.

      --- url: https://s2s.adjust.com/event?s2s=1&app_token=y0sxxx&event_token=4vexxx&gps_adid=ed6ec341-277c-43ce-b48d-xxx&partner_params=%257B%2522revenue%2522%253A%2520100%252C%2520%2522currency%2522%253A%2520%2522INR%2522%252C%2520%2522environment%2522%253A%2520%2522production%2522%257D
      
      
      --- code: 200
      --- rsp: {
          "status": "OK"
      }
      

复用 Facebook 的 app id

Google 账号被封, 新的 Google 包可以复用 Facebook 的 app id, 然后 fb 的广告账号就不用重新开户了, sdk 能正常获取到 fb 的广告数据, 也就可以正常解析为 动态渠道.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蝶泳奈何桥.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值