競合する除外キーワードと共有設定

除外キーワードを使うと、広告が関連性の低い検索結果に表示されないように設定できます。ただし、除外キーワード リストに不適切なマッチタイプがあると、通常のキーワードのマッチタイプが意図せずにブロックされて、キャンペーンの効果が弱まってしまう場合があります。

このガイドでは、AdWords API を使って、競合する除外キーワードを自動で取り除く方法について説明します。また、共有設定を使って、除外キーワードとプレースメントを管理する方法についても説明します。

シナリオ

たとえば、経営している紳士服店で男性用アクセサリーの冬休み特別キャンペーンを実施して、サイトへのトラフィックを増やしたいと考えているとします。最近実行した検索語句レポートから、女性用のシルクのスカーフが検索された場合にも、男性用アクセサリーのキャンペーンの広告が表示されていることがわかりました。

キーワード リストには「silk ties」、「wool scarves」、「men's gifts」という部分一致キーワードが含まれています。除外キーワードとして「silk scarves」を追加する場合、どの除外キーワードのマッチタイプが適切か考えてみます。

次の表では、いくつかの検索語句を例に、3 つの除外キーワードのマッチタイプそれぞれで広告がブロックされるかどうかを示しています。

検索語句 除外キーワード
-silk scarves
(除外キーワード、部分一致)
-"silk scarves"
(除外キーワード、フレーズ一致)
-[silk scarves]
(除外キーワード、完全一致)
mens scarves
mens ties
scarves silk 禁止マーク
silk ties
silk gift scarves 禁止マーク
silk scarves 禁止マーク 禁止マーク 禁止マーク
silk scarves gifts 禁止マーク 禁止マーク
silk ties wool scarves 禁止マーク
womens silk scarves 禁止マーク 禁止マーク
wool scarves

部分一致の除外キーワード -silk scarves の場合、「silk ties wool scarves」のような検索語句が意図せずにブロックされてしまいます。

競合する除外キーワードを一括で特定する

設定しているキーワードが少なければ、キーワード(非除外キーワード)と除外キーワードが競合するケースを特定するのは簡単です。しかし、何百や何千ものキーワードや除外キーワードがアカウントに設定されているような場合は、大幅に難しくなります。AdWords API を使ってこの作業を自動化する方法を見てみましょう。

説明を簡単にするために、ここでは、広告グループ単位のキーワードとキャンペーン単位の除外キーワードのみを考慮します。

除外キーワードを取得する

キャンペーン単位の除外キーワードのリストを取得するには、次のようにキャンペーンの除外キーワード パフォーマンス レポートを実行します。

def retrieve_negative_keywords(report_utils)
  report_definition = {
    :selector => {
      :fields => ['CampaignId', 'Id', 'KeywordMatchType', 'KeywordText']
    },
    :report_name => 'Negative campaign keywords',
    :report_type => 'CAMPAIGN_NEGATIVE_KEYWORDS_PERFORMANCE_REPORT',
    :download_format => 'CSV',
    :date_range_type => 'TODAY',
    :include_zero_impressions => true
  }

  campaigns = {}

  report = report_utils.download_report(report_definition)
  # Slice off the first row (report name).
  report.slice!(0..report.index("\n"))

  CSV.parse(report, { :headers => true }) do |row|
    campaign_id = row['Campaign ID']

    # Ignore totals row.
    if row[0] != 'Total'
      campaigns[campaign_id] ||= Campaign.new(campaign_id)
      negative = Negative.from_csv_row(row)
      campaigns[campaign_id].negatives << negative
    end
  end

  return campaigns
end

キーワード(非除外キーワード)を取得する

キーワード(非除外キーワード)のリストを取得するには、キーワード パフォーマンス レポートを実行します。allowed_values パラメータを使うと、ステータスに応じてキャンペーン、広告グループ、キーワードを除外できます。また、値として PAUSED および REMOVED を受け取ることができます。

def retrieve_positive_keyword_report(report_utils, allowed_values)
  report_definition = {
    :selector => {
      :fields => ['CampaignId', 'CampaignName', 'AdGroupId', 'Id',
                  'KeywordMatchType', 'KeywordText'],
      :predicates => [
        {
          :field => 'CampaignStatus',
          :operator => 'IN',
          :values => allowed_values
        },
        {
          :field => 'AdGroupStatus',
          :operator => 'IN',
          :values => allowed_values
        },
        {
          :field => 'Status',
          :operator => 'IN',
          :values => allowed_values
        },
        {
          :field => 'IsNegative',
          :operator => 'IN',
          :values => ['false']
        }
      ]
    },
    :report_name => 'Ad group keywords',
    :report_type => 'KEYWORDS_PERFORMANCE_REPORT',
    :download_format => 'CSV',
    :date_range_type => 'TODAY',
    :include_zero_impressions => true
  }

  report = report_utils.download_report(report_definition)
  # Slice off the first row (report name).
  report.slice!(0..report.index("\n"))

  return report
end

競合する除外キーワードを特定する

除外キーワードは、以下のロジックに従って機能します。

  • 部分一致の除外キーワードを設定すると、検索語句に除外キーワードの単語がすべて含まれる場合に、その検索語句がブロックされます。たとえば、-silk scarves の場合、「silk gift scarves」はブロックされますが、「wool scarves」はブロックされません。
  • フレーズ一致の除外キーワードを設定すると、検索語句に除外キーワードのすべての単語が 1 つのフレーズとして含まれる場合に、その検索語句がブロックされます。たとえば、-"silk scarves" の場合、「gift silk scarves」はブロックされますが、「silk gift scarves」はブロックされません。
  • 完全一致の除外キーワードを設定すると、キーワードと検索語句が完全に一致する場合にのみ、その検索語句がブロックされます。たとえば、-[silk scarves] の場合、「silk scarves」はブロックされますが、「red silk scarves」はブロックされません。
  • キーワードの大文字と小文字は区別されません。
  • 除外キーワードには、類似パターン一致は適用されません。たとえば、-silk scarves の場合、「silk scarf」は「silk scarves」の類似パターンですが、ブロックされません。

次のメソッドはこのロジックを実装しています。

def compare_keywords(negatives, positive)
  negatives.each do |negative|
    match_type = negative.match_type.downcase
    negative_text = negative.text.downcase
    positive_text = positive.text.downcase

    match = false

    # Exact matching with negative keywords triggers only when the full text of
    # the keywords is exactly the same.
    # E.g. a negative "silk scarves" will only match "silk scarves", not
    # "red silk scarves".
    if match_type == 'exact'
      match = (negative_text == positive_text)
    end

    # Phrase matching with negative keywords triggers when the negative phrase
    # is present in the target, completely unmodified.
    # E.g. a negative "silk scarves" will match "gift silk scarves", but not
    # "silk gift scarves".
    if match_type == 'phrase'
      negative_tokens = negative_text.split(' ')
      positive_tokens = positive_text.split(' ')

      positive_tokens.each_with_index do |positive_token, positive_index|
        # Iterate until the current token matches the first token in the
        # negative keyword.
        if positive_token == negative_tokens.first
          candidate_match = true
          # Do all of the subsequent tokens also match?
          negative_tokens[1..-1].each_with_index do |token, index|
            if token != positive_tokens[positive_index + index + 1]
              candidate_match = false
              break
            end
          end

          match = candidate_match
        end
      end
    end

    # Broad matching with negative keywords triggers when all of the words are
    # present and exactly the same.
    # E.g. a negative "silk scarves" will match "silk gift scarves", but not
    # "wool scarves".
    if match_type == 'broad'
      negative_tokens = negative_text.split(' ')
      positive_tokens = positive_text.split(' ')

      candidate_match = true

      negative_tokens.each do |token|
        if !positive_tokens.include?(token)
          candidate_match = false
          break
        end
      end

      match = candidate_match
    end

    negative.add_blocked(positive) if match
  end
end

競合する除外キーワードを削除する

競合する除外キーワードを特定したら、次のいずれかを行います。

  • CampaignCriterionService を使って、競合する除外キーワードを削除する。
  • レポートを生成して、手動で削除する。

この作業は定期的に行い、キーワードや除外キーワードのリストを変更した場合に新たな競合が発生していないかを確認する必要があります。

コードサンプルの全文

上記で使用しているコードサンプルの全文は、AdWords API Ruby クライアント ライブラリに含まれています。

共有設定

複数のキャンペーンで、意図しない広告表示やクリックを発生させているキーワードまたはプレースメントがある場合は、AdWords で除外キーワードやプレースメント共通のリストを作成して、すべてのキャンペーンに追加することができます。この機能は共有設定と呼ばれます。

共有設定では、アカウント内で設定内容を重複させる必要がないため、除外キーワードやプレースメントの除外を効果的に管理できます。

ここでは、AdWords API を使って、共有設定を作成して連携する方法について説明します。

コードサンプルは、AdWords API Java ライブラリを使用しています。その他のサポートされているクライアント ライブラリにもコードサンプルがあります。

共有設定を作成する

除外キーワードの共有設定を使うには、まず共有設定を作成する必要があります。次に、除外するキーワードのリストを使ってデータを入力します。次のコード スニペットでは、SharedSetService を使って、除外キーワードの共有設定を作成しています。


// Create the operation.
SharedSetOperation operation = new SharedSetOperation();
operation.setOperator(Operator.ADD);

// Create the shared set.
SharedSet sharedSet = new SharedSet();
sharedSet.setName("API Negative keyword list for demo");

// Set the type of the shared set. This may be negative keywords or placements.
sharedSet.setType(SharedSetType.NEGATIVE_KEYWORDS);
operation.setOperand(sharedSet);

SharedSetReturnValue retval = sharedSetService.mutate(
    new SharedSetOperation[] {operation});
for (SharedSet set : retval.getValue()) {
  System.out.println("Shared set with id = " + set.getSharedSetId() + ", name = " +
      set.getName() + ", type = " + set.getType() + ", status = " + set.getStatus() +
      "was created.");
}

共有設定を作成したら、SharedCriterionService を使って、新しく作成した共有設定にキーワードを追加できます。次のコード スニペットでは、共有設定に 2 つの新しいキーワードを追加しています。

String[] keywordTexts = new String[] {"mars cruise", "mars hotels"};

List operations = new ArrayList();
for (String keywordText: keywordTexts) {
  // Create the shared criterion.
  Keyword keyword = new Keyword();
  keyword.setText(keywordText);
  keyword.setMatchType(KeywordMatchType.BROAD);

  SharedCriterion sharedCriterion = new SharedCriterion();
  sharedCriterion.setCriterion(keyword);
  sharedCriterion.setNegative(true);
  sharedCriterion.setSharedSetId(sharedSetId);

  SharedCriterionOperation operation = new SharedCriterionOperation();
  operation.setOperator(Operator.ADD);
  operation.setOperand(sharedCriterion);
  operations.add(operation);
}

SharedCriterionReturnValue retval = sharedCriterionService.mutate(operations.toArray(
    new SharedCriterionOperation[operations.size()]));
for (SharedCriterion sharedCriterion : retval.getValue()) {
  Keyword keyword = (Keyword) sharedCriterion.getCriterion();
  System.out.println("Added keyword with id = " + keyword.getId() + ", text = " +
      keyword.getText() + ", matchtype = " + keyword.getMatchType() + " to shared " +
      "set with id = " + sharedSetId + ".");
}

memberCount フィールドを使うと、共有設定のキーワードやプレースメントの数を特定できます。また、referenceCount フィールドも、共有設定に関連するキャンペーンの数を確認できます。

共有設定をキャンペーンに適用する

共有設定を作成したら、CampaignSharedSetService を使って、複数のキャンペーンに共有設定を追加できます。次のコードでは、既存の共有設定をキャンペーンに追加する方法を示しています。

// Create the campaign shared set
CampaignSharedSet campaignSharedSet = new CampaignSharedSet();
campaignSharedSet.setCampaignId(campaignId);
campaignSharedSet.setSharedSetId(sharedSetId);

CampaignSharedSetOperation operation = new CampaignSharedSetOperation();
operation.setOperator(Operator.ADD);
operation.setOperand(campaignSharedSet);

CampaignSharedSetReturnValue retval = campaignSharedSetService.mutate(
    new CampaignSharedSetOperation[] {operation});
for (CampaignSharedSet attachedCampaignSharedSet : retval.value) {
  System.out.println("Attached shared set with id = " +
      attachedCampaignSharedSet.getSharedSetId() + " to campaign id " +
      attachedCampaignSharedSet.getCampaignId() + ".");
}

次に示すように、CampaignSharedSetService.get() メソッドを使って、既存のキャンペーンに適用されている共有設定を取得できます。

// Create the selector.
Selector selector = new Selector();
selector.setFields(new String[] {"SharedSetId", "CampaignId", "SharedSetName",
   "SharedSetType", "Status"});

// Filter your results by specific campaign id.
Predicate predicate = new Predicate();
predicate.setField("CampaignId");
predicate.setOperator(PredicateOperator.EQUALS);
predicate.setValues(new String[] {campaignId.toString()});

// Filter your results by the type of shared set.
Predicate predicate1 = new Predicate();
predicate1.setField("SharedSetType");
predicate1.setOperator(PredicateOperator.IN);
predicate1.setValues(new String[] {"NEGATIVE_KEYWORDS", "NEGATIVE_PLACEMENTS"});

selector.setPredicates(new Predicate[] {predicate});

CampaignSharedSetPage page = campaignSharedSetService.get(selector);
if (page.getEntries() != null) {
  for (CampaignSharedSet campaignSharedSet : page.getEntries()) {
    System.out.println("Shared set with id = " + campaignSharedSet.getSharedSetId() +
        ", name = " + campaignSharedSet.getSharedSetName() + ", type = " +
        campaignSharedSet.getSharedSetType() + " and status = " +
        campaignSharedSet.getStatus() + " was found.");
    }
  }
}

レポート

共有設定レポートを使うと、共有設定のレポートデータを取得できます。キャンペーン共有設定レポートでは、キャンペーン共有設定のレポートデータを取得できます。また、共有設定条件レポートでは、ダウンロード可能な共有設定条件のスナップショットを確認できます。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。