Wie man Labels über die AdWords API hinzufügt

Die AdWords API ist eine Bestie. Obwohl sie wirklich gut dokumentiert ist, dauert es eine ganze Weile, bis man sie voll begreift und die umfassenden Möglichkeiten durchsteigt. Kommt man jedoch damit zurecht, lassen sich großartige und wertvolle Dinge mit ihr anstellen, z.B. im Zusammenhang mit Labels. Heute möchte ich Euch daher eine Anleitung geben, wie man Labels programmatisch mit Ruby zu Keywords hinzufügt. 

Mehr Struktur dank Labels

Labels sind ein tolles Werkzeug, um Keywords, Kampagnen, Anzeigengruppen oder Anzeigen in AdWords mit Metadaten anzureichern. Labels sind wie Klebezettel, die es ermöglichen, AdWords-Elemente wie Keywords in aussagekräftigen Gruppen zusammenzufassen und zu filtern. Letztlich lässt sich damit ermitteln, welche Leistung die gekennzeichneten Elemente bringen und wie sie im Vergleich performen.

AdWords Label Filter

Wir hier bei crealytics nutzen unsere semantische SEA-Software camato, um große AdWords-Konten zu bewältigen, und Labels, um Daten effizient zu verwalten.

Labels via API Schritt für Schritt zu Keywords hinzufügen

Seit dem Release v201406 werden Labels von der API unterstützt, die Version v201409 hat diese Funktionen nochmals verbessert. Um es selbst nachmachen zu können, sollte man:

  1. grundlegende Kenntnisse der AdWords API haben,
  2. für die API angemeldet sein und die nötigen Zugangsdaten haben (bei Ruby packen wir die normalerweise in eine YAML-Datei),
  3. OAuth2-Tokens besitzen, um mit der API arbeiten zu können.

Legen wir also mit der ersten Klasse los. Sie liest die account-unabhängige API-Konfiguration ein:

module Adwords
  class Config

    ADWORDS_STATIC_CONFIG_FILE = "adwords_static_config.yml"

    def self.static_config
      static_file_path = File.join(Rails.root, "config", ADWORDS_STATIC_CONFIG_FILE)
      YAML.load(File.read(static_file_path))
    end

  end
end

Als nächstes erstellen wir einen AdWords Service Builder, indem wir die eingelesen Konfiguration mit der account-spezifischen OAuth-Konfiguration mergen:

require 'adwords_api'

class AdwordsServiceBuilder

  def self.service(adwords_id, service_name)
    config = self.config_hash(adwords_id)
    adwords_api = AdwordsApi::Api.new(config)
    adwords_api.service(service_name, adwords_api.config.read('api_version').to_sym)
  end

  private

  def self.config_hash(adwords_id)
    config = Adwords::Config.static_config
    oauth2_config = OAuthHandler.request_token(adwords_id).adwords_oauth2_token_config
    #Merge static and Oauth2 config
    config[:authentication][:oauth2_token] = oauth2_config
    config[:authentication][:client_customer_id] = adwords_id
    config
  end

end

Der Service Builder erleichtert den Zugriff auf die einzelnen Services der Adwords API. Mit seiner Hilfe können wir einen Wrapper für den Label Management Service erstellen:

class Labels

    def initialize(adwords_id)
      @label_service = AdwordsServiceBuilder.service(adwords_id, :LabelService)
    end

    #returns the id of the found / created label
    def find_or_create_label(label_text)
      response = label_service.get({fields: ['LabelName']})
      label_entry = find_label_entry(response, label_text)
      label_entry = create_label(label_text) unless label_entry
      label_entry[:id]
    rescue AdwordsApi::Errors::ApiException, AdsCommon::Errors::HttpError => e
      Rails.logger.error "Errors while finding creating labels #{e.message}"
      Rails.logger.error "e.backtrace.join('n')"
      raise e
    end

    private

    attr_reader :label_service

    def create_label(label_text)
      response = label_service.mutate([{operator: 'ADD',
	                                 operand: {xsi_type: 'TextLabel',
	                                   name: label_text}
	                               }])
      response[:value].first
    end

    def find_label_entry(response, label_text)
      if response[:entries].present?
	response[:entries].find{|e| e[:name] == label_text}
      end
    end

  end

Die eben erstellte Labels-Klasse liefert eine find_or_create Methode, die zuerst in einem AdWords-Konto anhand seines Textes nach einem Label sucht und dieses neu erstellt, falls das Label noch nicht existiert. Zur Erstellung des Labels nutzt es die Funktion label_service.mutate, welche das Google Adwords API Ruby gem nutzt, um mit dem LabelService zu interagieren. Die AdWords API wird als SOAP-Dienst bereitgestellt. Allerdings sind SOAP-Anfragen/-Antworten meist etwas hölzern, weshalb man das Ruby gem nutzt, welches eine nette Abstraktion über unverarbeitete SOAP-Anfragen liefert.

Jetzt, da wir ein Label erstellt haben, verbinden wir es mit einem Keyword:

class AdGroupCriterionService

    def initialize(keyword)
      @keyword = keyword
    end

    def update_with_label(label_id)
      ignore_label_exists_exception do
	service.mutate_label([add_label_operation(label_id)])
      end
    end

    private

    attr_reader :label_id, :keyword

    def service
      AdwordsServiceBuilder.service(keyword.adwords_id, :AdGroupCriterionService)
    end

    def add_label_operation(label_id)
      {
	xsi_type: "AdGroupCriterionLabelOperation",
	operator: 'ADD',
	operand: {
	  ad_group_id:  keyword.adgroupid,
	  criterion_id: keyword.id,
	  label_id:     label_id
	}
      }
    end

    def ignore_label_exists_exception(&block)
      begin
	block.call
      rescue AdwordsApi::Errors::ApiException, AdsCommon::Errors::ApiException => e
	if e.message.match(/AD_GROUP_CRITERION_LABEL_ALREADY_EXISTS/)
	  Rails.logger.warn("Trying to add a label which is already there")
	else
	  raise e
	end
      end
    end
  end

Um ein Label mit einem Keyword zu verbinden, nutzen wir die mutate_label Funktion des AdGroupCriterionService. Wir erstellen zudem ein Keyword-Modell, um die Keywords zu verwalten, die wir aus AdWords heruntergeladen haben.

Das Muster-(Rails) Keyword-Modell kann wie folgt aussehen:

class Keyword < ActiveRecord::Base
  belongs_to :account

  delegate :adwords_id, to: :account

  def update_label_in_adwords(label_text)
    label_id = Adwords::Labels.new(self.adwords_id)
	                      .find_or_create_label(label_text)
    Adwords::AdGroupCriterionService.new(self).update_with_label(label_id)
  end
end

Am Ende bleibt uns nur noch eines zu tun:

keyword = Keyword.find(params['keyword_id'].to_i)
keyword.update_label_in_adwords(params['label_text'])

That’s it, das AdWords API gem hat es uns ermöglicht, Labels zu erstellen und mit den Keywords elegant zu assoziieren.

Im Browser kann das wie folgt aussehen:

Add Labels AdWords

Die größten Hürden sind die Services richtig zu bauen, die korrekten Vorgänge abzurufen und mit den passenden Parametern durchzuführen. Das selbe Verfahren kann auch genutzt werden, um mit anderen Programmiersprachen wie Phyton oder Java mit der AdWords API zu interagieren.

Da dieses Feature der API nur dünn dokumentiert ist, glaube ich, dass der Beitrag für einige Entwickler dort draußen von Wert sein wird, und freue mich über Feedback.

ABOUT THE AUTHOR