纪晴丽 发表于 2025-6-1 00:04:10

苹果 ASA 广告归因对接实践与代码解析

在移动广告投放领域,精准的广告归因是衡量广告效果、优化投放策略的关键。苹果 Search Ads(ASA)作为苹果生态内重要的广告平台,如何准确获取并对接其广告归因数据,是开发者们必须解决的重要问题。今天就分享下我在苹果 ASA 广告归因对接中的实践经验和具体代码实现。
定义响应数据结构体

首先,定义用于接收苹果响应数据的结构体AppleAttributionResponse,它包含了广告归因的关键信息:
type AppleAttributionResponse struct {
    Attribution   bool   `json:"attribution"`
    OrgID         int64`json:"orgId"`
    CampaignID      int64`json:"campaignId"`
    ConversionTypestring `json:"conversionType"`
    ClickDate       string `json:"clickDate,omitempty"`
    ClaimType       string `json:"claimType"`
    AdGroupID       int64`json:"adGroupId"`
    CountryOrRegion string `json:"countryOrRegion"`
    KeywordID       int64`json:"keywordId"`
    AdID            int64`json:"adId"`
    ImpressionDatestring `json:"impressionDate,omitempty"`
}这个结构体里,Attribution表示归因是否成功;OrgID是组织 ID;CampaignID对应广告活动 ID 等,每个字段都与苹果返回的归因数据紧密相关 。
核心对接函数实现

在AoAPI结构体下,FetchAttributionFromApple函数负责从苹果获取广告归因数据,具体代码如下:
func (api *AoAPI) FetchAttributionFromApple(ctx *middleware.APIContext) (any, error) {
    var req struct {
      AttributionToken string `json:"token" binding:"required"`// 手机APP获取
      IDFV             string `json:"idfv"` // 设备ID
      IDFA             string `json:"idfa"` // 可选参数
    }

    // 解析请求参数
    if err := ctx.ShouldBindJSON(&req); err != nil {
      log.WithContext(ctx).WithError(err).Error("Failed to bind request")
      return nil, errs.InvalidArgument().WithError(err)
    }

    // 创建HTTP客户端
    client := &http.Client{
       Timeout: 10 * time.Second,
    }

    // 创建请求
    request, err := http.NewRequest("POST", "https://api-adservices.apple.com/api/v1/", bytes.NewBufferString(req.AttributionToken))
    if err != nil {
      log.WithContext(ctx).WithError(err).Error("Failed to create request")
      return nil, errs.Internal().WithError(err)
    }

    // 设置请求头
    request.Header.Set("Content-Type", "text/plain")

    // 发送请求
    response, err := client.Do(request)
    if err != nil {
      log.WithContext(ctx).WithError(err).Error("Failed to send request to Apple")
      return nil, errs.Internal().WithError(err)
    }
    defer response.Body.Close()

    // 检查响应状态码
    if response.StatusCode == http.StatusBadRequest {
      return nil, errs.InvalidArgument().WithCustomerHint("归因令牌无效")
    }
    if response.StatusCode == http.StatusNotFound {
      // 如果收到404,建议重试,间隔5秒,最多3次
      return nil, errs.NotFound().WithCustomerHint("未找到归因记录,请稍后重试")
    }
    if response.StatusCode == http.StatusInternalServerError {
      return nil, errs.Internal().WithCustomerHint("Apple Ads服务器暂时无法访问,请稍后重试")
    }
    if response.StatusCode != http.StatusOK {
      body, _ := io.ReadAll(response.Body)
      log.WithContext(ctx).Errorf("Apple returned error: %s", string(body))
      return nil, errs.Internal().WithCustomerHint("获取归因数据失败")
    }

    // 解析响应数据
    var attributionData AppleAttributionResponse
    if err := json.NewDecoder(response.Body).Decode(&attributionData); err != nil {
      log.WithContext(ctx).WithError(err).Error("Failed to decode response")
      return nil, errs.Internal().WithError(err)
    }
    // 业务处理*******
}函数执行流程如下:
解析请求参数:从请求中解析出AttributionToken、IDFV和可选的IDFA,若解析失败直接返回错误。
创建并发送请求:构建 HTTP POST 请求,设置好请求头后发送到苹果 ASA 广告归因接口,请求体为归因令牌。
处理响应:根据不同的响应状态码进行处理,如400表示归因令牌无效,404建议重试,500说明苹果服务器问题等。
解析响应数据:将响应数据解析到AppleAttributionResponse结构体中。
返回数据:直接返回解析后的关键归因数据,数据库操作部分因属于业务逻辑,在此省略 。
返回的数据格式示例如下:
{
    "attribution": true,
    "orgId": 1234567890,
    "campaignId": 1234567890,
    "conversionType": "Download",
    "claimType": "Click",
    "adGroupId": 1234567890,
    "countryOrRegion": "US",
    "keywordId": 12323222,
    "adId": 1234567890
}通过上述代码,我们实现了从苹果 ASA 获取广告归因数据并按需求返回的功能。实际使用时,还能根据业务需求优化代码,比如完善重试策略、增加监控等。如果你在对接过程中有任何问题,欢迎在评论区交流!

细节决定成败!
个人愚见,如有不对,恳请斧正!

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 苹果 ASA 广告归因对接实践与代码解析