【PHP】Google Ads APIで入札情報を更新したい！


#はじめに

サンプル使わずAPIでレポートデータを取得していたわけですが
[過去記事](https://qiita.com/azasaz/items/9a64c7c8d56d6692788b)

運用チームからの今度の要望は、
【Googleに登録している広告グループの入札情報を自サイトから直接更新したい】
というものでした。

ほーそうきたか。
まあいちいち管理画面にログインするのメンドクサイもんね。。
分からんでもないね。

ってなわけで今回は、
これまでどおりサンプルプログラム（Googleが用意してくれてる「クライアントライブラリ」ってやつ）は
使わない前提で（ここまできたら意地でも使いたくない！！）
「更新ってどうすりゃいいの！？」ってお話です。

今回のは基本的に全部マニュアル見れば書いてあったのだけど、
欲しい情報があっちゃこっちゃ飛び散っちゃってたのでまとめたくらいの、
メモ書き程度の内容になります。

何度も繰り返しますが、
公式ではクライアントライブラリを使うことを推奨してますので、
ここでのやり方はあくまでも参考として見てくださいネ！

#前提


oAuth2でのAPIアクセスはアクセストークンが必須ですので、
そこが取れなきゃお話になりません。

ということで、上述の過去記事を参考にしてoAuth2認証をします。

リフレッシュトークンとクライアントID、クライアントシークレットから
アクセストークンを取得するという作業になります。

アクセストークンを取得できたら、ヘッダーを作成します。
こんなかんじに。

```
//ヘッダー情報をセット
$_header = [
    "Content-Type: application/json", 
    "Accept: application/json",
    "Authorization: Bearer $access_token", 
    "developer-token: $developer_token",
    "login-customer-id: $login_customer_id",
];
```

これができたら準備はOK！

#更新

レポートデータはHeaderさえセットできればあとはクエリ言語で全部取ってこれたのですが、
マスタ系の更新には必ず「リソース名」が必要になります。

今回は広告グループを更新するので、こんなかんじ。

```
//クライアントID
$clientid = "CLIENT_ID";

//広告グループID：管理画面で確認できます
//※追加する場合は[-1]など存在しない値をセット
$adgroupid = "ADGROUP_ID";

//リソース名
$_resourcename = "customers/$clientid/adGroups/$adgroupid";

```

処理に呼び出すメソッドは**【Mutate】**。

使い方の詳細はこちら：
[公式リファレンス](https://developers.google.com/google-ads/api/docs/rest/common/mutate)

今回は広告グループの値を更新するので、POSTするURLは

```
$_url = "$_endpoint/$_version/customers/$clientid/adGroups:mutate";
```

実際にセットする値は、
operationsの下にcreate/update/removeを指定します。
（removeは試してないからよくわからんけど）

今回は、広告グループの中でも

・名前
・目標コンバージョン単価
・目標費用対効果
・デフォルトの上限クリック単価
・上限CPM
・目標インプレッション単価

を更新します。
ステータスも変更できます。

正常処理が完了すると、リソース名が返ってきます。


```
//updateMask【必須】：update対象のカラム名をカンマ区切りで全部指定
$_setting["operations"][0][0]["updateMask"] = "name,target_cpa_micros,target_roas,cpc_bid_micros,cpm_bid_micros,target_cpm_micros";

//リソース名【必須】
$_setting["operations"][0][0]["update"]["resourceName"] = $_resourcename;

//広告グループ名
$_setting["operations"][0][0]["update"]["name"] = "広告グループ TEST-1";

//目標コンバージョン単価：NULLで値のリセットが可。リセットした場合、キャンペーンのデフォルト単価が適用される（Google広告の仕様）
//microsなので値に×1000000する。セットする際は文字列にしないとエラーになる
$_targetcpa = 10000;
$_setting["operations"][0][0]["update"]["target_cpa_micros"] = strval($_targetcpa * 1000000);

//目標費用対効果：NULLで値のリセットが可。
//指数なので値に÷100する。セットする際は文字列にしないとエラーになる
$_targetroas = 200;
$_setting["operations"][0][0]["update"]["target_roas"] = strval($_targetroas / 100);

//デフォルトの上限クリック単価：NULLや０入力不可。必ず１以上（microsなので正確には1000000以上）を指定する。
//microsなので値に×1000000する。セットする際は文字列にしないとエラーになる
$_cpcbid = "100";
$_setting["operations"][0][0]["update"]["cpc_bid_micros"] = strval($_cpcbid * 1000000);

//上限CPM：NULLや０入力不可。必ず１以上（microsなので正確には1000000以上）を指定する。
//microsなので値に×1000000する。セットする際は文字列にしないとエラーになる
$_cpmbid = "100";
$_setting["operations"][0][0]["update"]["cpm_bid_micros"] = strval($_cpmbid * 1000000);

//目標インプレッション単価：NULLや０入力不可。必ず１以上（microsなので正確には1000000以上）を指定する。
//microsなので値に×1000000する。セットする際は文字列にしないとエラーになる
$_targetcpm = 100;
$_setting["operations"][0][0]["update"]["target_cpm_micros"] = strval($_targetcpm * 1000000);

//curl START
$_curl = curl_init();

//OPTIONをセット
curl_setopt_array($_curl, array(
    CURLOPT_URL => $_url,
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 120,
    CURLOPT_HTTPHEADER => $_header,
    CURLOPT_POSTFIELDS => json_encode($_setting),
));

//curl EXEC(文字列で取得)
$_resp = curl_exec($_curl);
//エラーハンドリング用
$_errno = curl_errno($_curl);

//curl END
curl_close($_curl);

//エラーハンドリング
if ($_errno !== CURLE_OK) {
    //エラー処理
}

//エラーでなければjsonを連想配列化        
$_result_json = json_decode($_resp, true); 
$_result = is_array($_result_json["results"]) ? $_result_json["results"] : [];

//リソース名が戻ってこれば正常終了
if ($_result[0]["resourceName"] == $_resourcename) {
    return true;
}

```

数値にどんな値を入れるかは、公式ドキュメントに割と親切に書いてあるので、そちらをよく参照してください。

エラーの場合はエラーコードとメッセージが返ってきます。
こんなかんじに：

>{ "error": { "code": 400, "message": "Request contains an invalid argument.", "status": "INVALID_ARGUMENT", "details": [ { "@type": "type.googleapis.com/google.ads.googleads.v6.errors.GoogleAdsFailure", "errors": [ { "errorCode": { "operationAccessDeniedError": "MUTATE_ACTION_NOT_PERMITTED_FOR_CLIENT" }, "message": "A mutate action is not allowed on this campaign, from this client.", "trigger": { "stringValue": "VIDEO" }, "location": { "fieldPathElements": [ { "fieldName": "operations", "index": 0 } ] } } ] } ] } }

ちなみにこれは、更新できない項目をUPDATEしようとしてエラーになったものです。
割と細かくエラー内容を教えてくれる印象でしたね。

#おわりに

今回は割とさらっと更新出来ました。少しだけ扱いに慣れてきたのかも。

GoogleAPI難しくて途方に暮れてる方の一助になりますように。。

次はv6から新たに追加された更新履歴の取得に取り掛かりまーす！