Google広告のキーワード除外リスト更新ってスマホアプリからできないの?!
という課題から、ChatGPTを用いてVibeCodingでGASを作って解決しました。
この記事ではその完成品のサンプルコードを配りたいと思います。
実際のワークフロー構造としてはこのようになります。
・Google広告のキーワード除外リスト更新をスマホからスプシを操作
・GASから実行(トリガーを毎日と設定すれば毎日実行)*またはPCから手動で実行ボタンで運用するなど
Google広告の除外リストとは?

ツール > 共有ライブラリ > 除外リストよりアクセスできる、広告配信対象から除外するキーワードを管理しておくリストです。ここへの追加を自動化するのが今回のコードになります。
STEP1. 除外リスト管理用のスプシを用意し、そのIDを控える

URLを見ると以下のようになっているかと思います。
スプシのIDとは、以下でいうところの [1234abc567qwerty] です。
https://docs.google.com/spreadsheets/d/1234abc567qwerty/edit?gid=0#gid=0
Step2. Google広告管理画面内にGASを追加
場所:Google広告管理画面 > ツール > 一括操作 > スクリプト > +マーク

STEP3. 以下のGASコードを追加
なお、前提として
・<<スプシID>> には入力が必要です
・「除外リスト」という名称のシートだと仮定しています
function main() {
const SPREADSHEET_ID = '<<スプシID>>';
const SHEET_NAME = '除外リスト'; // タブ名
const START_ROW = 2; // ヘッダ1行想定
const isPreview = AdsApp.getExecutionInfo().isPreview();
Logger.log('MODE: ' + (isPreview ? 'PREVIEW' : 'RUN'));
Logger.log('Account: ' + AdsApp.currentAccount().getCustomerId());
const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME);
const lastRow = sheet.getLastRow();
if (lastRow < START_ROW) { Logger.log('No data'); return; }
// A:keyword / B:listname / C:results
const rows = sheet.getRange(START_ROW, 1, lastRow - START_ROW + 1, 3).getValues();
// 共有ライブラリの除外キーワードリストをキャッシュ
const listsMap = {};
const it = AdsApp.negativeKeywordLists().get();
const listNames = [];
while (it.hasNext()) {
const l = it.next();
listsMap[l.getName()] = l;
listNames.push(l.getName());
}
Logger.log('Found lists: ' + listNames.join(', '));
for (let i = 0; i < rows.length; i++) {
const rawKw = (rows[i][0] || '').toString().trim();
const listName = (rows[i][1] || '').toString().trim();
const imported = (rows[i][2] === true);
if (!rawKw || !listName || imported) continue;
// マッチタイプ付与:[] or "" がなければデフォルトでフレーズ一致にする
const kw = normalizeToPhraseIfBare_(rawKw);
const list = listsMap[listName];
if (!list) { Logger.log(`NOT FOUND list: ${listName}`); continue; }
// 既存チェック(同一文字列があればスキップ)
if (hasKeywordExactText_(list, kw)) {
Logger.log(`EXISTS: ${kw} in [${listName}]`);
if (!isPreview) sheet.getRange(START_ROW + i, 3).setValue(true);
continue;
}
if (isPreview) {
Logger.log(`PREVIEW would add: ${kw} -> [${listName}]`);
continue;
}
try {
list.addNegativeKeyword(kw); // ここが正式API
Utilities.sleep(300); // 反映待ち
if (hasKeywordExactText_(list, kw)) {
sheet.getRange(START_ROW + i, 3).setValue(true);
Logger.log(`ADDED: ${kw} -> [${listName}]`);
} else {
Logger.log(`FAILED (post-check not found): ${kw} -> [${listName}]`);
}
} catch (e) {
Logger.log(`ERROR add: ${kw} -> [${listName}] : ${e.message}`);
}
}
Logger.log('done.');
}
// [] / "" がなければ "..." を付けてフレーズ一致に正規化
function normalizeToPhraseIfBare_(text) {
const t = text.trim();
if (/^\[.*\]$/.test(t) || /^".*"$/.test(t)) return t; // 既に完全 or フレーズ
return `"${t}"`; // デフォルトはフレーズ一致
}
// リスト内に文字列が完全一致で存在するか(getText() は記号含む文字列を返す)
function hasKeywordExactText_(list, textWithMatch) {
const it = list.negativeKeywords().get();
while (it.hasNext()) {
if (it.next().getText() === textWithMatch) return true;
}
return false;
}
STEP4. プレビューしてから実行
これで除外リストに追加完了です。
なお、MCCアカウントを使っている場合は、小アカウントの画面にしたうえで実行する必要があるようなのでご注意ください。
(STEP5. 定期実行設定)

こちらはお好みですが、Frequencyで定期実行可能です。
なお、生成AIへの依頼の仕方を共有

かなーり雑でも成功しました。
まずはじめに以下のような話だしがあったうえで、
検索広告をインタレストマッチで出稿すると、全く関係ないキーワードにも出稿されてしまい、他社出稿者から除外するように問い合わせが多数届きます。 これをスマホから除外することのできるアプリはありますか? あるいはフレーズ一致の方が良い?
スマホアプリはないと言われます。
ではGASかZapierかn8nあたりで…ということで、まずGASで試そうと思い、以下で依頼しました。
GASサンプル欲しいです。
なお、
・スプシに書き込むと除外キーワード内の任意のリストに取り込まれる
・スプシから取り込んだら、取り込み済みキーワードにはフラグが立つ
・フラグが立っているキーワードは取り込まない といった形を希望します
この先は、エラーを潰す地道な作業です。(が、わたしはコードをほぼ読まずにエラーを潰せました)
また、フラグ管理がうまく動作せず、むしろ手動管理したほうがよさそうなので途中で取り外しました。
このようにChatGPTなど生成AIを上手にもちいることで、業務改善が可能ですね。


コメント