So erstellen Sie die perfekte Amazon-Kampagnenstruktur mit Hilfe von Python und Bulk-Operations

Cover Image for So erstellen Sie die perfekte Amazon-Kampagnenstruktur mit Hilfe von Python und Bulk-Operations
Trutz Fries
Trutz Fries

In diesem Artikel zeigen wir Ihnen, wie Sie die Programmiersprache Python und das Pandas-Package nutzen, um die erforderlichen Tabellen-Sheets zu erstellen, die Sie für die Arbeit mit Bulk-Operations auf Amazon benötigen.

Was sind Amazon Advertising Bulk-Operations?

Amazon Advertising Bulk-Operations (Wir nennen sie "Bulk-Sheets") sind Excel Sheets, welche Ihre komplette Kampagnenstruktur, inklusive der relevanten Leistungskennzahlen, enthalten.

Sie können hier entweder neue Kampagnen erstellen oder aber bereits vorhandene Kampagnen mit Bulk-Sheets aktualisieren.

Amazon Bulk Sheets in der Amazon Advertising-Konsole
In dieser Abbildung sehen Sie die Option zum Upload sowie Download von Bulk-Sheets in der Amazon Advertising-Konsole.

Bulk Sheets sind besonders nützlich, wenn Sie beispielsweise eine große Menge an Kampagnen gleichzeitg erstellen oder updaten möchten, ohne den gleichen Prozess für jede Kampagne einzeln durchlaufen zu müssen.

Angenommen, Sie möchten das Budget für jede Ihrer 400 Sponsored Products Kampagne mit einem ACoS von unter 20% um 10% erhöhen. Auch wenn dies in der Amazon Advertising Konsole problemlos möglich wäre, bietet die Option der Bulk-Sheets eine deutlich smartere Lösung zum aktualisieren dieser.

Der Prozess hierzu läuft folgendermaßen ab:

  1. Downloaden Sie die aktuellen Bulk-Sheets in der Amazon Advertising Konsole.
  2. Öffnen Sie die Datei beispielsweise in Microsoft Excel und öffnen Sie das Tabellenblatt "Sponsored Products".
  3. Filtern Sie das Tabellenblatt nach der Kampagne, die Sie aktualisieren möchten.
  4. Ändern sie die Spalte: "Budget"
  5. Sichern Sie die Datei und laden Sie diese erneut auf Amazon hoch.

Dennoch möchten wir uns heute nicht nur anschauen, wie Sie bereits existierende Kampagnen aktualisieren, sondern insbesondere, wie Sie neue Kampagnen für Ihre Produkte erstellen.

Was ist die perfekte Kampagnenstruktur?

Wir kreieren für jedes einzelne Produkt bzw. für jede einzelne Produktfamilie typischerweise spezifische Kampagnen.

Wir erstellen z.B. die folgenden manuellen Sponsored Product Kampagnen:

  • Eine Kampagne mit generischen Keyword-Targets (generisch bedeutet, dass das Keyword keine Markennamen enthält).
  • Eine Kampagne mit offensiven Keyword-Targets (offensiv bedeutet, dass wir Marken der Konkurrenz angreifen).
  • Eine Kampagne mit offensiven Produkt-Targets (welche Produkte der Konkurrenz enthält).
  • Eine Kampagne mit defensiven Keyword-Targets (defensiv bedeutet, dass wir auf Keywords bieten, welche unseren Markennamen oder unsere Produktnamen enthalten).
  • Eine Kampagne mit defensiven Produkt-Targets (welche unsere Produkte anzielt).

Dies tun wir, weil offensive, generische und defensive Kampagnen typischerweise unterschiedliche performen. So ist es z.B. deutlich "günstiger" auf Ihre eigene Marke, als auf die Marken Ihrer Konkurrenz zu bieten. Generische Kampagnen sind typischerweise "günstiger" als offensive Kampagnen, aber z.B. "teurer" als defensive Kampagnen. Dies bedeutet, dass Sie unterschiedliche Performance-Ziele für jeden Kampagnentyp definieren müssen. Wenn der ACoS Ihr Hauptziel ist, brauchen Sie für offensive Kampagnen höhere ACoS-Ziele als für defensive Kampagnen.

Wenn Sie alle Targets in einer Kampagne vereinen würden, so würden Sie einen "Gemischtwarenladen" erhalten. Sie könnten diese Kampagne zwar sicherlich z.B. nach Ihrem Target-ACoS verwalten, aber wie würden Sie in diesem Falle Ihr Budget zuordnen? Wie würden Sie z.B. höhere Budgets für Ihre defensive Kampagne, als für Ihre offensive Kampagne zulassen? Dies wäre nicht möglich und ein weiterer Grund dafür, warum wir unsere Kampagnen aufteilen.

Die Erstellung dieser fünf Kampagnen für jedes Produkt/jede Produktfamilie erfordert jedoch einiges an Arbeit. Genau hier kommt nun unser automatisiertes Verfahren durch Python zum Einsatz.

Wie Sie ein neues Bulk-Sheet mit Python erstellen

Um ein Bulk Sheet zu erstellen, benötigen wir zunächst einige Informationen:

  • Welche ASINs (Vendoren) oder SKUs (Seller) sollen beworben werden?
  • Was sind Ihre eigenen sowie Konkurrenz-Marken?
  • Welche sind die Keywords, auf die sie bieten möchten?
  • Welches sind die Produkte, auf die sie bieten möchten?

Diese Informationen sollten Sie z.B. in einer anderen Excel-Tabelle oder Google Docs Datei verwalten. Wir verwalten diese Information beispielweise in einer separaten Textdatei, welche wir mit Hilfe von weiteren Skripten mehr oder weniger automatisiert aus bereits vorhandenen (aber unorganisierten) Kampagnen erstellen können. Eine detailierte Erklärung hierzu würde den Rahmen dieses Artikels allerdings sprengen und müsste in einem separaten Artikel erläutert werden.

Unterschiedliche Textdateien für Produkt- und Keywordinformationen
Produkt- und Keywordinformationen werden in separaten Textdateien abgespeichert

Diese Dateien erstellen wir jeweils für jede ASIN, SKU oder Gruppe von ASINs/SKUs.

Unser Skript durchläuft anschließend die einzelnen Dateien dieses Ordners und erstellt hieraus die bereits erwähnten fünf Kampagnen für jedes Produkt / jede Produktgruppe. Ihre Aufgabe besteht hierbei einzig aus dem Ausfüllen der Dateien, dem Ausführen des Skriptes und dem Hochladen der Bulk-Sheets.

Hier sind die wichtigsten Bestandteile des Skripts. Es würde zu viel Platz beanspruchen, jede einzelne Zeile des Codes zu zeigen, daher konzentrieren wir uns auf die wichtigsten Dinge.

Setup einiger Variablen

Wenn wir ein neues Bulk-Sheet erstellen, ist es wichtig die Struktur des Bulk-Sheets inklusive der unterschiedlichen Entitäten zu verstehen. So müssen Sie für eine Kampagne andere Werte definieren als für eine Anzeigegruppe oder ein Keyword-Target.

Wenn Sie z.B. eine neue Kampagne mit Anzeigengruppen und z.B. Keyword-Targets erstellen wollen, müssen Sie hierzu folgende Felder ausfüllen: (Diese finden Sie wenn Sie z.B. ein ausgefülltes Bulk-Sheet herunterladen)

emptySpBulksheet = {
    "Product": "Sponsored Products",
    "Entity": "",
    "Operation": "Create",
    "Campaign Id": "",
    "Ad Group Id": "",
    "Portfolio Id": "",
    "Ad Id (Read only)": "",
    "Keyword Id (Read only)": "",
    "Product Targeting Id (Read only)": "",
    "Campaign Name": "",
    "Ad Group Name": "",
    "Start Date": "",
    "End Date": "",
    "Targeting Type": "",
    "State": "",
    "Daily Budget": "",
    "SKU": "",
    "ASIN": "",
    "Ad Group Default Bid": "",
    "Bid": "",
    "Keyword Text": "",
    "Match Type": "",
    "Bidding Strategy": "",
    "Placement": "",
    "Percentage": "",
    "Product Targeting Expression": ""
}

Dies sind die Spalten, welche ausgefüllt werden müssen. Einige Spalten gehören jedoch speziellen Entitäten an. Die Daily Budget Spalte bezieht sich z.B. nur auf die Kampagnen-Entität.

Das gleiche gilt z.B. auch für Sponsored Brands sowie Sponsored Display Kampagnen.

Anschließend definieren wir einige Variablen, welche das "Verhalten" von unserem Skript bestimmen. Hierzu einige Beispiele:

# Campaign
createSPCampaigns = True
campaignStatus = "Enabled" # Enter “Enabled”, “Paused”, or “Archived”
campaignDailyBudget = 20 # EUR or USD
campaignBiddingStrategy = 'Dynamic bids - down only' # Enter "Dynamic bids - down only", "Dynamic bids - up and down", or "Fixed bid".
campaignStartDate = time.strftime("%Y%m%d") # Today as default, e.g. "20220529"
campaignEndDate = "" # “yyyymmdd”, can be empty

# Adgroup (https://advertising.amazon.com/API/docs/en-us/bulk sheets/sp/sp-entities/sp-entity-ad-group)
adgroupMaxBix = 1.50 
adgroupStatus = "Enabled" # Enter “Enabled”, “Paused”, or “Archived”

# Keyword
keywordDefaultMatchType = 'broad'
negativeKeywordDefaultMatchType = 'negativeExact' # negativePhrase or negativeExact

# Toggles: Here you can define which type of targets to create (true) or not (false)
addKeywordsGeneric   = True
addKeywordsDefensive = True
addKeywordsOffensive = False
addProductsOffensive = False
addProductsDefensive = False

Dasselbe gilt auch für die anderen Anzeigetypen (Sponsored Brands, Sponsored Display).

Zusätzliche Informationen für externe Sheets

In manchen Fällen nutzen auch wir Excel-Dateien, welche zusätzliche Informationen enthalten. Diese ermöglichen unseren Mitarbeiteren einen teilweise einfacheren Umgang bei der Arbeit mit diesen.

Nehmen wir an, wir hätten ein seperates Sheet, dessen Dateiname unter der Variable mainInputFile mit folgenden zwei Tabellenblättern gespeichert ist:

  • Unsere Marken- und Produktnamen
  • Konkurrierende Marken- und Produktnamen

Um diese Marken in unsere Python Skript zu transferieren, würden wir folgendes tun:

# Read additional data from main input file (Google Doc -> Excel Sheet)
xls = pd.ExcelFile(mainInputFile)
dfB = pd.read_excel(xls, engine="openpyxl", sheet_name="Our brands")
dfC = pd.read_excel(xls, engine="openpyxl", sheet_name="Competitor brands")

ownBrands        = dfB['Brand'].unique().tolist()
competitorBrands = dfC['Brand'].unique().tolist()

# Make sure brands are lowercase
ownBrands = list(map(str.lower, ownBrands))
competitorBrands = list(map(str.lower, competitorBrands))

Anschließend führen wir eine Datenbereinigung durch und wandeln alle Buchstaben in Kleinbuchstaben um, was zu einer besseren Vergleichbarkeit beiträgt.

Theoretisch könnte man diesen Schritt auch "fest" in das Skript integrieren. Die Arbeit mit einem externen Sheet ermöglicht uns hierbei allerdings einen flexibleren Umgang, was praktisch ist, wenn Sie mit mehreren Kunden arbeiten, so wie wir es tun.

Methoden zu Erstellung von Kampagnen, Werbegruppen usw.

Im nächsten Schritt defnieren wir einige Hilfsfunktionen, mit denen wir das Bulk-Sheet aufbauen können.

Hier als Beispiel die Methode zur Festlegung des Kampagnennamens:

def getCampaignName(targeting = "Manual", campaignType = "SP", type1="keyword", type2 = "generic", groupName = "default" ):
    
    prefix = "RE-" + campaignType + "-"
    
    # targeting
    if targeting == "Manual":
        targetingPrefix = "MANU-"
    else:
        targetingPrefix = "AUTO-"
        
    # type1
    if type1 == "keyword":
        type1Prefix = "KW-"
    else:
        type1Prefix = "PT-"
    
    # type 2
    if type2 == "generic":
        type2Prefix = "GEN-"
    elif type2 == "offensive":
        type2Prefix = "OFF-"
    else:
        type2Prefix = "DEF-"
    
    groupName = groupName.strip()
    groupName = groupName[:30].upper()
    
    campaignName = prefix + targetingPrefix + type1Prefix + type2Prefix + groupName + '-' + randomString
    
    return campaignName

Wie Sie sehen, beginnt unser Kampagnen-Name mit einem Präfix, welcher uns ermöglicht diese vereinfacht zu identifizieren. Anschließend fügen wir folgende Strings hinzu:

  • MANU oder AUTO wenn es sich hierbei um eine manuelle oder automatisierte Kampagne handelt (Nur für Sponsored- Product Kampagnen)
  • KW oder PT wenn es sich hierbei um ein Keyword- oder Product-Targeting handelt
  • GEN, OFF oder DEF für die verwendeten Target-Typen (generisch, offensiv oder defensiv)
  • Den Namen der Produkte / Produktgruppen
  • Einen zufälligen String, welcher sich bei jedem Durchlauf des Skripts ändert.

Dieser zufällige String ermöglichst es Ihnen, nach Kampagnen, die in einem einzelnen Durchlauf erstellt wurden, zu filtern. Wenn Ihnen bei der Erstellung der Kampagnen ein Fehler unterlaufen ist, lassen sich diese so einfacher finden und z.B. archivieren. Lassen Sie diesen Schritt also keinesweg aus, Sie werden mir später hierfür danken!

Anschließend erstellen wir die verschiedenen Methoden um weitere Enitäten zu erschaffen. Hier finden Sie z.B. eine Methode, um die relevanten Felder auszufüllen, die für die Erstellung einer Kampagne benötigt werden.

def createSpCampaign(targeting = "Manual", type1="none", type2 = "none", groupName = "none", customerPath = "none", counter = 1, fileName = "" ):

    global bulkSheetSp
    
    campaignName = getCampaignName(targeting = targeting, campaignType = "SP", type1=type1, type2 = type2, groupName = groupName)
    
    campaign = copy.deepcopy(emptySpBulksheet) # Create a deep copy
    
    campaign['Entity']           = 'Campaign'
    campaign['Campaign Id']      = campaignName
    campaign['Campaign Name']    = campaignName
    campaign['Start Date']       = campaignStartDate
    campaign['End Date']         = campaignEndDate
    campaign['Targeting Type']   = targeting.upper()
    campaign['State']            = campaignStatus
    campaign['Daily Budget']     = campaignDailyBudget
    campaign['Bidding Strategy'] = campaignBiddingStrategy
    
    if ((bulkSheetSp['Entity'] == 'Campaign') & (bulkSheetSp['Campaign Id'] == campaignName)).any():
        pass # Do nothing, we already have this campaign
    else:
        bulkSheetSp = bulkSheetSp.append(campaign, ignore_index=True)
    
    # Create adgroup          
    createSpAdgroup(targeting = targeting, type1=type1, type2 = type2, groupName = groupName, campaignName = campaignName, customerPath = customerPath, counter = counter, fileName = fileName)

In diesem Falle kopieren wir uns unser leeres Bulk-Sheet und füllen dieses mit allen erforderlichen Daten. Dieses ruft im Anschluss die Methode: createSpAdgroup auf, welche equivalent zu der vorher genannten Methode abläuft, nur für eine Anzeigengruppe.

Die Methode sieht folgendermaßen aus:

def createSpAdgroup(targeting = "Manual", type1="none", type2 = "none", groupName = "none", campaignName = 'none', customerPath = "none", counter = 1, fileName = ""):
    
    counterString = f"{counter:02}"
    
    global bulkSheetSp
    
    adgroupName  = getCampaignName(targeting = targeting, campaignType = "SP", type1=type1, type2 = type2, groupName = groupName) + '-AG' + '-' + counterString
    
    adgroup = copy.deepcopy(emptySpBulksheet) # Create a deep copy to not alter emptySpBulksheet
    
    adgroup['Entity']        = 'Ad Group'
    adgroup['Campaign Id']   = campaignName
    adgroup['Ad Group Name'] = adgroupName
    adgroup['Ad Group Id']   = adgroupName
    adgroup['State']         = adgroupStatus
    adgroup['Ad Group Default Bid'] = adgroupMaxBix
        
    bulkSheetSp = bulkSheetSp.append(adgroup, ignore_index=True)

    # Create ad
    
    createSpAd(targeting = targeting, type1=type1, type2=type2, groupName=groupName, campaignName=campaignName, adgroupName=adgroupName, customerPath = customerPath)
    
    if type1 == "keyword":
        createSpKeywordTarget(targeting = targeting, type1=type1, type2=type2, groupName=groupName, campaignName=campaignName, adgroupName=adgroupName, customerPath = customerPath, fileName = fileName)

    if type1 == "product":
        createSpProductTarget(targeting = targeting, type1=type1, type2=type2, groupName=groupName, campaignName=campaignName, adgroupName=adgroupName, customerPath = customerPath)

Alle anderen Methoden, die zur Erstellung von Anzeigen, Keyword-Targets, negativen Keywords usw. benötigt werden, definieren wir auf dieselbe Art und Weise.

Kick-off - Das Bulk-Sheet erstellen

Final benötigen wir unser Hauptskript, welches alles in Gang setzt.

Dieses sieht wie folgt aus:

if createSPCampaigns:
    
    # Create empty bulksheet
    bulkSheetSp = pd.DataFrame(data=emptySpBulksheet, index=[0])

    # Get all products or product groups stored in different folders
    productGroups = list_paths(customerPath)
    productGroupsLength = len(productGroups)

    j = 0

    randomString = randStr(N=5) # Create a random string

    for productGroup in productGroups:
        
        j = j + 1
        
        # Check which files are available
        all_files = sorted(glob.glob(customerPath  + '/' + productGroup + '/*.txt'))
        
        counter = 0

        for file in all_files:

            if (addKeywordsOffensive) & ('keywords-offensive.txt' in file):
                createSpCampaign(targeting = "Manual", type1="keyword", type2 = "offensive", groupName = productGroup, customerPath = customerPath, fileName = file)
            
            if (addKeywordsGeneric == True) & ('keywords-generic.txt' in file):
                counter = counter + 1
                createSpCampaign(targeting = "Manual", type1="keyword", type2 = "generic", groupName = productGroup, customerPath = customerPath, counter = counter, fileName = file)
            
            if (addKeywordsDefensive) & ('keywords-defensive.txt' in file):
                createSpCampaign(targeting = "Manual", type1="keyword", type2 = "defensive", groupName = productGroup, customerPath = customerPath, fileName = file)
            
            if (addProductsDefensive) & ('products-defensive.txt' in file):
                createSpCampaign(targeting = "Manual", type1="product", type2 = "defensive", groupName = productGroup, customerPath = customerPath, fileName = file)
            
            if (addProductsOffensive) & ('products-offensive.txt' in file):
                createSpCampaign(targeting = "Manual", type1="product", type2 = "offensive", groupName = productGroup, customerPath = customerPath, fileName = file)

Aus didaktischen Gründen habe ich einige Zeilen entfernt, z.B. um die Dateien zu säubern, bevor wir sie parsen (leere Zeilen entfernen usw.). Wir können dabei auch mit mehr als 1.000 Keywords umgehen, der maximalen Anzahl von Keywords in einer Anzeigengruppe. Dies kann schnell passieren, wenn Sie mit Permuationen arbeiten, weil Sie bei einem Broad-Match einen Phrase-Match verwenden wollen. In diesem Fall teilt das Skript die Keywords auf mehrere Anzeigengruppen auf.

Zu guter Letzt müssen wir unsere Daten in eine Excel-Tabelle exportieren, die wir anschließend bei Amazon hochladen können.

Dies funktioniert in Python folgendermaßen:

# Remove empty rows
if createSPCampaigns:
    bulkSheetSp['Entity'].replace('', np.nan, inplace=True)
    bulkSheetSp.dropna(subset=['Entity'], inplace=True)

# Filename
today = time.strftime("%Y-%m-%d-%H-%M") # Today as default
outputFile = customerPath + '/' + today + '-' + slugify(customer) + '-campaign-create-bulksheet.xlsx'
outputFile = outputFile.replace("input-", "")

# Export to Excel
with pd.ExcelWriter(outputFile) as writer:  
    if createSPCampaigns:
        bulkSheetSp.to_excel(writer, sheet_name='Sponsored Products Campaigns', index=False)

Zusammenfassung

Und das war`s auch schon. Sobald Sie alles vorbereitet haben, können Sie Ihrer Kreativität freien Lauf lassen, um die txt-Dateien oder ihr Haupt-Input-Sheet zu füllen:

Hier sind einige Ideen für den Anfang:

  • Generieren Sie Ideen für Keywords und Produkt-Targets auf der Grundlage des Suchbegriff Berichtes in Brand-Analytics
  • Verwenden Sie hier auch die Keywords aus Ihrer Amazon SEO-Recherche

Falls unser Kunde uns den Auftrag erteilt, bestehende Kampagnen neu zu organisieren und gut funktionierende Keywords zu nutzen, analysieren wir z.B. die bestehenden Bulk-Sheets und extrahieren alle Produkte einschließlich der gut performenden Targets. Anschließend ordnen wir jedes Target in den richtigen Bereich (offensiv, defensiv, generisch) ein und führen das Skript innerhalb weniger Minuten aus. So lassen sich auch unorganisierte Kampagnen vergleichsweise schnell neu strukturieren.

Sie brauchen Unterstützung?Nehmen Sie Kontakt mit uns auf.

Zoom Call

Footer

Unser Newsletter

Ich habe die Datenschutzerklärung gelesen und stimme dieser zu.

REVOIC ist verifizierter EU Agency Platinum Partner.REVOIC ist verifizierter Amazon Advertising Partner.
REVOIC ist Amazon Marketplace EU Agency Platinum Partner sowie Amazon Advertising Verified Partner.

Made with ♥ in Köln-Ehrenfeld