AIによるGoogle広告の除外キーワード自動化

AIによるGoogle広告の除外キーワード自動化

FlowHuntはAIを活用してGoogle広告の除外キーワード管理を自動化し、企業のコスト削減、広告費の最適化、そしてキャンペーン成果の向上をサポートします。

無駄なキーワード費用の理解

無駄なキーワード費用とは、あなたの広告が実際に販売している商品やサービスと合わない検索結果に表示されてしまうことで発生します。こうした無関係なクリックは、売上につながらないのに費用だけがかかってしまい、予算をすぐに消費してしまいます。たとえば、高級レザーシューズを販売する会社が「靴を買う」のような幅広いキーワードを設定した場合、スニーカーやサンダルを探している人からのクリックも集めてしまい、本来のターゲットではない顧客に広告費が使われてしまいます。このようなキーワードのミスマッチは、広告費の無駄遣いやROIの低下につながります。無駄な支出を避け、適切なキーワードに予算を集中させるためにも、こうした仕組みを理解することが重要です。

除外キーワードの役割

除外キーワードは、すべてのGoogle広告キャンペーンにとって不可欠なツールです。広告主は、特定の検索語句を除外キーワードとして設定することで、無関係な検索では広告が表示されないようにできます。たとえば、「安い」や「割引」などを除外キーワードにすることで、高級レザーシューズの会社は、プレミアム商品に興味のないユーザーからのクリックを避けることができます。除外キーワードを丁寧にリストアップすることで、広告費の最適化、無駄なクリックの削減、そしてキャンペーン全体の効果向上が期待できます。

AIによるキーワード管理

人工知能(AI)は、Google広告キャンペーンの管理方法を大きく変えつつあります。FlowHuntのようなAIツールは、キーワードのグルーピングに特化しており、関連キーワードの特定と整理をより効率的に行えます。これにより、ポジティブ(狙いたい)キーワードも除外キーワードも、手作業による管理の負担を大幅に減らすことができます。AI主導のキーワード管理は、パフォーマンスデータに基づきリアルタイムで変更を加えることができるため、広告費を常に最適化し、最大のROIを実現します。

無駄なキーワード費用を減らす戦略

無駄なキーワード費用を削減するには、以下の戦略を取り入れましょう:

  • キーワードリストを定期的に更新し、市場トレンドや消費者の関心の変化に合わせる。
  • 強力な除外キーワード戦略を実践し、除外したい語句を常にリサーチ・更新する。
  • パフォーマンスデータをもとにキャンペーンを監視・調整する。
  • 売上につながるキーワードとそうでないキーワードを分析し、ターゲティング精度を高め広告費を最大化する。

事例紹介:PostAffiliateProの取り組み

PostAffiliateProは、毎月の広告費に課題を抱え、Google広告キャンペーンから思うようなROIが得られていませんでした。そこでAIの導入を決断。AI駆動のツールを取り入れることで、キーワード管理プロセスを自動化し、ポジティブ・ネガティブ両方のキーワードをより正確に特定しました。この変化により、広告費を最適化し、コストを大幅に削減、キャンペーン効率も向上しました。新しいキーワードの分析は、最初のインプレッションから1時間以内に実行されます。このスピード感は、訪問者がGoogle広告をクリックする前に、除外すべきキーワードを素早く検出するのに役立ちます。

improved conversion rate コンバージョン率の向上(関連性の高い検索だけが売上につながります)

追加リソース

効果的なキーワード管理やAI最適化についてさらに学びたい方は、以下のリソースもご覧ください:

新しいキーワードを評価するGoogle広告スクリプト

以下は、キーワードクラスタを評価するために毎時実行しているスクリプトです。

このスクリプトは、Google広告キャンペーン管理に関するさまざまなタスクを自動化することを目的としています。設定用のGoogleスプレッドシートと連携し、検索語句の分析やキーワードの追加・除外、さらに高度なAIキーワードクラスタリングのためにFlowHunt APIとの連携を行います。

Google Sheet to manage script settings Googleスプレッドシートでスクリプト設定を管理

Negative keywords automatically applied to Ad groups 除外キーワードが広告グループに自動適用される様子

メイン関数

  • コアとなる制御ロジックはmain()関数に格納されています。この関数は、spreadsheetURLで指定されたGoogleスプレッドシートを開き、apiKeycountrylanguageなど必要な設定を取得します。
  • まず、すべての新しいポジティブキーワードをFlowHuntクラスタに追加しようと試みます。成功した場合のみ、未割り当ての検索語句の分析に進みます。

キーワード分析

  • 未割り当て語句の分析: アカウント内のすべての広告グループ(指定ラベル付き)をループし、Google広告で現在ターゲットしていないがインプレッションがあった検索語句を取得します。
  • システムはFlowHunt APIを利用して、現在分析中のキーワードに類似する検索語句を抽出し、指定したminimumMatch基準でフィルタリングします。
  • 基準に合致した語句はポジティブキーワードとして追加し、合致しなかったものは除外キーワードとしてマーク。結果はGoogleスプレッドシートに記録され、Google広告キャンペーンにも反映されます。

FlowHunt連携

  • API連携: callFlowHuntApi()関数により、ワークスペースIDの取得やキーワードクラスタリングなど、さまざまなタスクをFlowHunt APIとやり取りします。
  • キーワードのクラスタ追加: ポジティブキーワードはFlowHuntに返送され、Google広告から得たライブ検索クエリデータも反映してクラスタリングされます。
  • 追加済み・除外済みキーワードは、それぞれ別のシートで記録・トラッキングします。

使い方

このスクリプトを導入するには、以下の手順が必要です:

  • 有効なGoogleスプレッドシートURLを用意し、「Settings」「AddedKW」「NegativeKW」のシートが存在することを確認してください。
  • FlowHuntのAPIキーや国コード等、正しい情報でスプレッドシートの設定を行ってください。
  • Google広告スクリプト環境で、必要なAPIアクセスが有効になっていることを確認し、スクリプトを実行してください。

Add script to your Google Ads in menu Tools -> Bulk Actions -> Scripts Google広告の「ツール」→「一括操作」→「スクリプト」メニューにスクリプトを追加してください。

Googleスプレッドシートへの実際のリンクを設定するのをお忘れなく。あとは私たちの魔法にお任せください。キャンペーンに属するキーワードを検出し、(ポジティブ・ネガティブ両方の)キーワード管理を自動化します。

除外キーワードを自動管理するGoogle広告スクリプト

//Global variables
var spreadsheetURL;
var spreadsheet;
var sheetSettings; 
var sheetAddedKW;
var sheetNegativeKW;
var apiKey;
var labelName;
var country;
var language;
var location;
var urlsCount;
var minimumMatch;
var workspaceId;

function main() {
    // Provide the Google Sheets URL here
  spreadsheetURL = "https://docs.google.com/spreadsheets/d/....... FULL URL TO GOOGLE SHEET";
  spreadsheet = SpreadsheetApp.openByUrl(spreadsheetURL);
  sheetSettings = spreadsheet.getSheetByName("Settings"); 
  sheetAddedKW = spreadsheet.getSheetByName("AddedKW");
  sheetNegativeKW = spreadsheet.getSheetByName("NegativeKW");
  apiKey = getSettingValue("FlowHuntAPIkey")
  labelName = getSettingValue("LabelName")
  country = getSettingValue("CountryCode")
  language = getSettingValue("LanguageCode")
  location = getSettingValue("Location")

  urlsCount = getSettingValue("TopUrlsCount")
  minimumMatch = getSettingValue("MinimumMatch")
  workspaceId = getWorkspaceId()
  
  if (workspaceId.length < 10) {
    Logger.log("Failed to load workspace id from FlowHunt, check API key");
    return;
  }
  
  Logger.log("FlowHunt WorkspaceId: " + workspaceId);
  
  if (addPositiveKWsToCluster() == 0) {
    // Analyze new keywords just if all positive keywords added already
    analyzeNotAssignedWords();
  }
}

function analyzeNotAssignedWords() {
  Logger.log("*** START Checking not assigned keywords");
  
  // Iterate through all ad groups in the account
  var adGroupsIterator = AdsApp.adGroups().get();
  
  while (adGroupsIterator.hasNext()) {
    var adGroup = adGroupsIterator.next();
    var groupName = adGroup.getId() + " - " + adGroup.getName();
    if (hasLabel(adGroup, labelName)) {
      // Get the search terms for the current ad group ordered by clicks in the last X days
      var searchTermsQuery = "SELECT Query FROM SEARCH_QUERY_PERFORMANCE_REPORT " +
        "WHERE AdGroupId = " + adGroup.getId() +
        " AND QueryTargetingStatus = \"NONE\" " +
        "DURING TODAY";

      var searchTermsIterator = AdsApp.report(searchTermsQuery).rows();
      var adGroupKeywords = [];
      while (searchTermsIterator.hasNext()) {
        var searchTerm = searchTermsIterator.next();
        var searchTermText = searchTerm["Query"].trim();
        var similarQueries = getSimilarQueries(groupName, searchTermText)
        var filteredSimilarQueries = getFilteredSimilarQueries(similarQueries);
        if (filteredSimilarQueries.length > 0) {
          var keywordOperation = adGroup.newKeywordBuilder().withText("[" + searchTermText + "]").build();
          if (keywordOperation.isSuccessful()) {
            adGroupKeywords.push(searchTermText);
            var rowData = [groupName, searchTermText, new Date(), "ADDING AS POSITIVE, REVIEW!", JSON.stringify(filteredSimilarQueries)];
            sheetAddedKW.appendRow(rowData);
          } else {
            Logger.log("Failed to add keyword as positive:" + searchTermText)
          }
        } else {
          // add to negative
           adGroup.createNegativeKeyword("[" + searchTermText + "]");
          Logger.log("Excluded search term in ad group '" + groupName + "': " + searchTermText);
          var rowData = [groupName, "[" + searchTermText + "]", new Date(), JSON.stringify(similarQueries)];
          sheetNegativeKW.appendRow(rowData);
        }
      }
      if (adGroupKeywords.length > 0) {
        //Add all keywords in the list to FlowHunt Cluster
        addKeywordsToFlowHunt(groupName, adGroupKeywords);
      }
    }
  }
  Logger.log("*** FINISHED Checking not assigned keywords");
}

function getSimilarQueries(groupName, query) {
  result = callFlowHuntApi("/serp/serp/cluster/query_intersections?workspace_id="+workspaceId, "POST", {
    "query": query,
    "country": country,
    "language": language,
    "location": location,
    "group_name": groupName,
    "live_mode": true,
    "max_position": urlsCount
  });
  Logger.log(result)
  if (result.status=="SUCCESS") {
    return JSON.parse(result.result);
  }
  return []
}

function getFilteredSimilarQueries(similarQueries) {
  filtered = [];
  for (var i=1; i<similarQueries.length; i++){
    if (similarQueries[i].count>=minimumMatch) {
      filtered.push(similarQueries[i]);
    }
  }
  return filtered;
}

function addPositiveKWsToCluster() {
  Logger.log("*** START Checking new campaign keywords");
  // Iterate through all ad groups in the account
  var adGroupsIterator = AdsApp.adGroups().get();
  var processedKWs = sheetAddedKW.getDataRange().getValues();
  var processedKWsMap = {};
  var rowsAdded = 0;
  
  for (var i = 1; i < processedKWs.length; i++) { // Start at 1 to skip header row if exists
    var groupName = processedKWs[i][0];
    var keyword = processedKWs[i][1];
    processedKWsMap[groupName + '|' + keyword] = true;
  }
  
  while (adGroupsIterator.hasNext()) {
    var adGroup = adGroupsIterator.next();
    var groupName = adGroup.getId() + " - " + adGroup.getName();
    if (hasLabel(adGroup, labelName)) {
      var keywordsIterator = adGroup.keywords().get();
      var adGroupKeywords = [];
      while (keywordsIterator.hasNext()) {
        var keyword = keywordsIterator.next();
        if (keyword.isEnabled()) {
          var key = groupName + '|' + keyword.getText();
          if (!processedKWsMap[key]) {
            adGroupKeywords.push(keyword.getText());
            var rowData = [groupName, keyword.getText(), new Date(), "Already present in campaign"];
            sheetAddedKW.appendRow(rowData);
            processedKWsMap[key] = true; 
          }
        }
      }
      if (adGroupKeywords.length > 0) {
        //Add all keywords in the list to FlowHunt Cluster
        addKeywordsToFlowHunt(groupName, adGroupKeywords);
      } else {
        Logger.log("No new keywords in Group: " + groupName);
      }
      rowsAdded = rowsAdded + adGroupKeywords.length
    }
  }
  Logger.log("*** FINISHED Checking new campaign keywords");
  return rowsAdded;
}

function addKeywordsToFlowHunt(GroupName, adGroupKeywords) {
  requests = []
  adGroupKeywords.forEach(function(keyword) {
    requests.push(
        {
          "query": keyword,
          "country": country,
          "language": language,
          "location": location,
          "group_name": GroupName,
          "count_urls": 30
        }
      );
    });
  callFlowHuntApi("/serp/serp/cluster/add_queries?workspace_id="+workspaceId, "POST", {"requests":requests});
}

function getSettingValue(settingName) {
    var data = sheetSettings.getDataRange().getValues();
    for (var i = 0; i < data.length; i++) {
        if (data[i][0] === settingName) {
            return data[i][1];
        }
    }
    return null;
}
  
function getWorkspaceId() {
  result = callFlowHuntApi("/auth/me", "GET")
  if (result !== null) {
    return result.api_key_workspace_id;
  }
}

function callFlowHuntApi(endpoint, method, requestBody) {
    var url = "https://api.flowhunt.io/v2" + endpoint;
    var headers = {
        "Api-Key": apiKey,
        "Content-Type": "application/json"
    };
    var options = {
        "method" : method,  // or "post", "put", etc.
        "headers" : headers,
        "payload": JSON.stringify(requestBody)
    };
    
    try {
        var response = UrlFetchApp.fetch(url, options);
        var responseData = JSON.parse(response.getContentText());
        Logger.log(responseData);
        return responseData;
    } catch (e) {
        Logger.log("An error occurred: " + e.message);
    }
    return null;
}

function hasLabel(adGroup, labelName) {
  var labels = adGroup.labels().get();
  while (labels.hasNext()) {
    var label = labels.next();
    if (label.getName() === labelName) {
      Logger.log("Processing Adgroup " + adGroup.getName());
      return true;
    }
  }
  return false;
}

よくある質問

Google広告で除外キーワードが重要なのはなぜですか?

除外キーワードを使うことで、広告が無関係な検索に表示されるのを防ぎ、無駄な費用を削減し、本当に関連性の高い検索に絞ってROIを向上させることができます。

AIはどのように除外キーワード管理を自動化しますか?

FlowHuntのようなAIツールはリアルタイムの検索データを分析し、無関係なキーワードを特定、自動的に除外キーワードとしてキャンペーンに追加することで、手間を省き効率を向上させます。

AIで除外キーワードを自動化するとどんな効果が期待できますか?

AIが継続的にキーワードリストやターゲティングを最適化することで、コンバージョン率の向上、無関係なクリックによる広告費の削減、キャンペーンの効率アップが期待できます。

自分のGoogle広告でFlowHuntの自動化を設定するには?

Google広告アカウントを接続し、Googleスプレッドシート上で設定を行い、提供されるスクリプトをデプロイすることで、FlowHuntのAIによる自動キーワード管理が利用できます。

ヴィクトル・ゼマンはQualityUnitの共同所有者です。20年以上会社を率いてきた今も、主にソフトウェアエンジニアとして、AI、プログラム的SEO、バックエンド開発を専門としています。LiveAgent、PostAffiliatePro、FlowHunt、UrlsLabなど、数多くのプロジェクトに貢献してきました。

ヴィクトル・ゼマン
ヴィクトル・ゼマン
CEO、AIエンジニア

AIでGoogle広告を自動化

Google広告のROIを最大化しませんか?AIによる自動化で除外キーワードを管理し、広告費を最適化する方法をご紹介します。

詳細はこちら

ネガティブクエリ自動化によるPPC AIエージェント
ネガティブクエリ自動化によるPPC AIエージェント

ネガティブクエリ自動化によるPPC AIエージェント

FlowHuntのPPC AIエージェントでGoogle広告のネガティブキーワードを自動化。無関係なクエリを除外し、無駄な広告費を削減、AIによるターゲティングと手間のかからないキャンペーン最適化でコンバージョンを向上させます。...

1 分で読める
PPC AI +3
検索語句の分離はPPC広告最適化の鍵
検索語句の分離はPPC広告最適化の鍵

検索語句の分離はPPC広告最適化の鍵

検索語句の分離がPPC広告の最適化に不可欠な理由を解説。高パフォーマンスな検索語句をターゲットにし、ROI向上・コスト削減・キャンペーン効率化を、マッチタイプ・除外キーワード・自動化ツールで実現する方法をご紹介します。...

1 分で読める
PPC Search Term Isolation +5
PPC最適化とキーワードグルーピングの理解
PPC最適化とキーワードグルーピングの理解

PPC最適化とキーワードグルーピングの理解

PPCキャンペーンを最適化し、キーワードグルーピングをマスターして高い関連性、品質スコアの向上、より良いROI、効果的なキャンペーン管理を実現する方法を学びましょう。広告グループの構成、ランディングページの連携、除外キーワードの活用など、実践的なヒントやツール、ベストプラクティスをご紹介します。...

2 分で読める
PPC Keyword Grouping +4