概览
CloudX Unity SDK 设置和核心功能概览
CloudX Unity SDK 使您能够在 iOS 和 Android 上通过横幅、MREC、插屏、激励和 App Open 广告实现 Unity 游戏变现。
安装
CloudX Unity SDK 以 .unitypackage 文件形式分发。
- 从 CloudX Unity SDK 4.5.1 发布页 下载
CloudXSdk-4.5.1.unitypackage - 在 Unity 中,转到 Assets > Import Package > Custom Package
- 选择下载的
.unitypackage文件 - 提示时导入所有资源
广告网络适配器
CloudX SDK 需要广告网络适配器来投放广告。在 Assets/CloudXSdk/Editor/CloudXDependencies.xml 中取消注释相应行即可启用。各适配器的详细设置(包括 iOS Info.plist 要求),请参阅适配器章节。
初始化
在加载任何广告之前初始化 SDK。您可以在初始化之前选择性地配置用户和应用属性。
using CloudX;
using UnityEngine;
public class MyGameManager : MonoBehaviour
{
void Start()
{
InitializeCloudX();
}
void InitializeCloudX()
{
// 初始化前配置(可选)
CloudXSdk.SetHashedUserId("hashed-user-id");
CloudXSdk.SetUserKeyValue("user_level", "premium");
CloudXSdk.SetAppKeyValue("app_version", "1.0.0");
// 在初始化之前订阅回调
CloudXInitializationCallbacks.OnSdkInitializedEvent += OnSdkInitialized;
CloudXInitializationCallbacks.OnSdkInitializationFailedEvent += OnSdkInitializationFailed;
// 初始化 SDK
var config = CloudXInitializationConfiguration.Create("YOUR_APP_KEY").Build();
CloudXSdk.Initialize(config);
}
private void OnSdkInitialized(CloudXSdkConfiguration config)
{
Debug.Log("CloudX SDK 初始化成功");
// 现在可以加载广告
}
private void OnSdkInitializationFailed(CloudXError error)
{
Debug.LogError($"SDK 初始化失败: {error}");
}
}广告格式
CloudX Unity SDK 支持横幅、MREC、插屏、激励和 App Open 广告集成。请查阅各格式专属指南了解实现详情:
横幅广告和 MREC 广告
在固定屏幕位置展示广告,支持可选刷新控制。
插屏广告
加载并展示全屏插屏广告。
激励广告
用户完成激励广告观看后给予奖励。
App Open 广告
在用户打开应用或返回应用时展示全屏广告。
高级功能
隐私控制
如果您的应用没有使用 CMP,可以在初始化之前手动覆盖隐私状态。
// 在 Initialize() 之前可选地设置手动隐私覆盖
CloudXSdk.SetHasUserConsent(true);
CloudXSdk.SetDoNotSell(false);
// 传入 null 可清除手动覆盖,重新交由 CMP 或 IAB 信号决定
CloudXSdk.SetHasUserConsent(null);
CloudXSdk.SetDoNotSell(null);SetHasUserConsent(bool?)用于设置 GDPR 同意覆盖。SetDoNotSell(bool?)用于设置 CCPA do-not-sell 覆盖。- 如果存在 IAB 同意或隐私信号,它们会优先于这些手动覆盖值。
iOS ATT 使用说明文案
从 Unity SDK 2.2.4 开始,如果您的应用尚未在 Info.plist 中定义 NSUserTrackingUsageDescription,CloudX 的 iOS 后处理步骤会自动添加该字段。
- 默认值:
This uses device info for more personalized ads and content - 如果您已经提供了
NSUserTrackingUsageDescription,CloudX 会保留您现有的值不变。 - 如果您希望展示自定义的 ATT 提示文案,请在
Info.plist中显式设置自己的值。
用户定向
配置用户和应用属性以获得更好的广告定向。在 Initialize 之前调用这些方法。
// 设置哈希用户 ID
CloudXSdk.SetHashedUserId("hashed-user-id-12345");
// 设置用户级键值对
CloudXSdk.SetUserKeyValue("user_level", "premium");
CloudXSdk.SetUserKeyValue("age_group", "25-34");
// 设置应用级键值对
CloudXSdk.SetAppKeyValue("app_version", "1.0.0");
CloudXSdk.SetAppKeyValue("build_number", "123");
// 清除所有自定义键值对
CloudXSdk.ClearAllKeyValues();哈希用户 ID 是由发布商提供的假名标识符。当适用的隐私信号允许时,CloudX 会在竞价时记录该值,并在展示级收入导出中以 hashed_user_id 返回。您可以使用该值将 CloudX 收入与自己的用户数据分群关联。未设置 ID、隐私信号阻止持久化或值超过 128 个字符时,导出值为空。请勿传递未经哈希的个人数据。
身份透传
通过 SetUserKeyValue 传入 UID 2.0、EUID、LiveRamp 和 ID5。有值时设置一次,刷新后再设一次。
| 键 | 传入内容 |
|---|---|
uidapi.com | UID2 广告 token,不要传 refresh token。不要解密。UID2 文档 |
euid.eu | EUID 广告 token,不要传 refresh token。不要解密。EUID 文档 |
liveramp.com | LiveRamp ATS 信封,不要传 RampID。LiveRamp 文档 |
id5-sync.com | ID5 通用 UID。不要传 0。ID5 文档 |
CloudX 不会生成这些 ID。请先用 UID2、EUID、LiveRamp ATS 或 ID5 生成,再把字符串传进来。这与哈希用户 ID 不是同一回事。
CloudXSdk.SetUserKeyValue("uidapi.com", uid2Token);
CloudXSdk.SetUserKeyValue("euid.eu", euidToken);
CloudXSdk.SetUserKeyValue("liveramp.com", liveRampEnvelope);
CloudXSdk.SetUserKeyValue("id5-sync.com", id5Id);收入追踪
所有广告格式都通过 OnAdRevenuePaid 事件提供收入回调。CloudXAd 对象包含收入信息:
CloudXAdsCallbacks.Banner.OnAdRevenuePaid += (ad) =>
{
Debug.Log($"收入: ${ad.Revenue:F4}");
Debug.Log($"广告网络: {ad.NetworkName}");
Debug.Log($"广告单元: {ad.AdUnitId}");
Debug.Log($"广告格式: {ad.AdFormat}");
Debug.Log($"广告位: {ad.Placement}");
Debug.Log($"网络广告位: {ad.NetworkPlacement}");
// 在您的分析中追踪收入
TrackRevenue(ad.Revenue, ad.NetworkName);
};MMP 广告收入连接器
如果您的应用使用 Adjust 或 AppsFlyer,可以无需编写 Unity C# 胶水代码,直接将 CloudX 竞得展示收入转发给移动归因合作伙伴。请在 Assets/CloudXSdk/Editor/CloudXDependencies.xml 中取消注释连接器依赖,然后运行 EDM4U 依赖解析。
请只选择连接器或您自己的 OnAdRevenuePaid 转发代码其中一种方式,不要同时使用。
发布者上报的收入数据
如果您的应用在 CloudX 广告流程之外接收来自 AdMob、Google Ad Manager、InMobi、TopOn 或其他聚合平台的展示级收入回调或 bid 元数据,请在 CloudX 初始化完成后将这些事件转发给 CloudX:
| 字段 | 必填 | 描述 |
|---|---|---|
Platform | 是 | CloudXRevenuePlatform.AdMob、CloudXRevenuePlatform.Gam、CloudXRevenuePlatform.InMobi、CloudXRevenuePlatform.TopOn 或 CloudXRevenuePlatform.Custom("MyProvider") |
Revenue | 是 | 单次展示收入,使用 CurrencyCode 对应货币;不是 CPM/eCPM |
AdFormat | 是 | 广告格式字符串,例如 banner、mrec、interstitial 或 rewarded |
CurrencyCode | 否 | ISO 4217 货币代码(如已知) |
Precision | 否 | CloudXRevenuePrecision.Exact、Estimated、PublisherDefined 或 Undefined |
NetworkName | 否 | 获胜广告网络名称(如已知) |
AdUnitId | 否 | 聚合平台广告单元 ID |
ThirdPartyAdPlacementId | 否 | 广告网络侧广告单元或 placement ID |
CreativeId | 否 | 广告网络返回的创意 ID |
NetworkPlacement | 否 | 广告网络 placement 标识 |
CountryCode | 否 | 用户国家代码(如已知) |
UserSegment | 否 | 用户分群(如已知) |
当事件被 CloudX 收益链路接受时,CloudXSdk.ReportRevenueData() 返回 true。当 payload 无效、SDK 尚未初始化或收入追踪不可用时,它返回 false。
AdMob paid event
使用 Google Mobile Ads Unity 插件时,每个广告对象都会暴露 OnAdPaid。回调中的 AdValue.Value 以微单位上报,因此传给 CloudX 前请先除以 1_000_000.0。
private static CloudXRevenuePrecision ToCloudXRevenuePrecision(AdValue.PrecisionType precision) => precision switch
{
AdValue.PrecisionType.Precise => CloudXRevenuePrecision.Exact,
AdValue.PrecisionType.Estimated => CloudXRevenuePrecision.Estimated,
AdValue.PrecisionType.PublisherProvided => CloudXRevenuePrecision.PublisherDefined,
_ => CloudXRevenuePrecision.Undefined,
};
private static bool ReportAdMobPaidEvent(AdValue adValue, string adFormat, string adUnitId)
{
return CloudXSdk.ReportRevenueData(new CloudXRevenueData(
Platform: CloudXRevenuePlatform.AdMob,
Revenue: adValue.Value / 1_000_000.0,
AdFormat: adFormat,
CurrencyCode: adValue.CurrencyCode,
Precision: ToCloudXRevenuePrecision(adValue.Precision),
AdUnitId: adUnitId,
));
}
bannerView.OnAdPaid += adValue =>
{
ReportAdMobPaidEvent(adValue, "banner", ADMOB_BANNER_UNIT_ID);
};Google Ad Manager paid event
Google Ad Manager paid event 的上报方式与 AdMob paid event 相同,但需要使用 CloudXRevenuePlatform.Gam 和 Ad Manager 广告单元 ID。
private static bool ReportGamPaidEvent(AdValue adValue, string adFormat, string adUnitId)
{
return CloudXSdk.ReportRevenueData(new CloudXRevenueData(
Platform: CloudXRevenuePlatform.Gam,
Revenue: adValue.Value / 1_000_000.0,
AdFormat: adFormat,
CurrencyCode: adValue.CurrencyCode,
Precision: ToCloudXRevenuePrecision(adValue.Precision),
AdUnitId: adUnitId,
));
}
adManagerInterstitial.OnAdPaid += adValue =>
{
ReportGamPaidEvent(adValue, "interstitial", GAM_INTERSTITIAL_UNIT_ID);
};InMobi impression event
对于 InMobi,请在 OnAdFetchSuccessful 中保存 args.AdMetaInfo。当 OnAdImpression 触发时,把保存的 metaInfo.Bid 上报给 CloudX,然后清空保存的值。
private AdMetaInfo bannerMetaInfo;
private static bool ReportInMobiImpression(AdMetaInfo metaInfo, string adFormat, string placementId)
{
return CloudXSdk.ReportRevenueData(new CloudXRevenueData(
Platform: CloudXRevenuePlatform.InMobi,
Revenue: metaInfo.Bid,
AdFormat: adFormat,
Precision: CloudXRevenuePrecision.Estimated,
ThirdPartyAdPlacementId: placementId,
CreativeId: metaInfo.CreativeID,
));
}
bannerAd.OnAdFetchSuccessful += (_, args) =>
{
bannerMetaInfo = args.AdMetaInfo;
};
bannerAd.OnAdImpression += (_, _) =>
{
ReportInMobiImpression(bannerMetaInfo, "banner", INMOBI_BANNER_PLACEMENT_ID);
bannerMetaInfo = null;
};TopOn revenue event
使用 TopOn Unity plugin v2.1.8 或更高版本时,请在广告对象上设置 IATAdRevenueListener。使用 adInfo.publisher_revenue 作为单次展示收入;不要使用 adInfo.adsource_price,因为 TopOn 将该值作为 CPM/eCPM 上报。
using AnyThinkAds.Api;
using CloudX;
private static CloudXRevenuePrecision ToTopOnRevenuePrecision(string precision)
{
return precision switch
{
"exact" => CloudXRevenuePrecision.Exact,
"estimated" => CloudXRevenuePrecision.Estimated,
"publisher_defined" => CloudXRevenuePrecision.PublisherDefined,
_ => CloudXRevenuePrecision.Undefined,
};
}
private sealed class TopOnRevenueListener : IATAdRevenueListener
{
public void onAdRevenuePaid(string placementId, ATCallbackInfo adInfo)
{
ReportTopOnRevenue(adInfo, "banner", placementId);
}
}
private static bool ReportTopOnRevenue(ATCallbackInfo adInfo, string adFormat, string placementId)
{
return CloudXSdk.ReportRevenueData(new CloudXRevenueData(
Platform: CloudXRevenuePlatform.TopOn,
Revenue: adInfo.publisher_revenue,
AdFormat: adFormat,
CurrencyCode: adInfo.currency,
Precision: ToTopOnRevenuePrecision(adInfo.precision),
NetworkName: adInfo.network_name,
AdUnitId: placementId,
ThirdPartyAdPlacementId: adInfo.network_placement_id,
NetworkPlacement: adInfo.adsource_id,
CountryCode: adInfo.country,
));
}
ATBannerAd.Instance.setAdRevenueListener(TOPON_BANNER_PLACEMENT_ID, new TopOnRevenueListener());自定义平台事件
对于没有 CloudX SDK 内置常量的 provider,请使用 Custom;AdMob、Google Ad Manager、InMobi 和 TopOn 已有内置常量。这里的值只表示 provider 名称,例如 CloudXRevenuePlatform.Custom("TradPlus") 或 CloudXRevenuePlatform.Custom("Nimbus")。请保持名称稳定,便于 CloudX 一致归类该 provider 的收益。
不要把金额或币种放进 provider 名称里。如果一条 TradPlus 展示带来 USD 0.01 收入,请传 Platform: CloudXRevenuePlatform.Custom("TradPlus")、Revenue: 0.01 和 CurrencyCode: "USD"。如果来源返回 CPM/eCPM,请先除以 1_000.0。
private static bool ReportCustomRevenueEvent(
string providerName,
double revenue,
string adFormat,
string currencyCode,
string adUnitId,
string placementId)
{
return CloudXSdk.ReportRevenueData(new CloudXRevenueData(
Platform: CloudXRevenuePlatform.Custom(providerName),
Revenue: revenue,
AdFormat: adFormat,
CurrencyCode: currencyCode,
Precision: CloudXRevenuePrecision.PublisherDefined,
AdUnitId: adUnitId,
ThirdPartyAdPlacementId: placementId,
));
}