跳至主要内容

搜索引擎营销(SEM)的数据科学

在本教程中,数据科学遇见搜索引擎营销:学习用 Python 生成关键词和广告模板,创建 Google AdWords 广告系列!
· 15分钟 阅读

使用 AI 探索

作为 DataCamp 的重度用户已有两年时间,我学到了不少东西。我的主营业务是在线营销,而我从所学的数据科学技能中获益良多。现在我能够管理规模更大、结构更复杂的广告系列,并高效维护它们。由于我已经相当熟悉网站上的内容、各个主题以及 R 和 Python 的不同软件包,我就想以练习为目的,试着为 DataCamp 创建搜索广告系列。

在本教程中,您将涉及以下主题:

  • 首先进一步了解搜索引擎营销(SEM)和搜索广告系列;
  • 然后,深入审视当前的业务案例;
  • 接着,您将为 DataCamp 的讲师、技术、课程和主题生成关键词。
  • 在获得关键词后,您就可以开始生成广告。您会先制定策略,然后开始创建广告模板。

搜索引擎营销(SEM)与广告系列

什么是 SEM?

在竞争日益激烈的市场中,SEM 是发展业务最有效的方式之一。它是通过在搜索引擎上购买广告来获取网站流量的过程。Google AdWords 是最流行的线上广告形式之一:您为与业务相关的关键词在搜索引擎的赞助链接中争取广告位,然后为每次点击向搜索引擎支付费用。

按点击付费的成本可能相当可观,因此合理规划并分组关键词和广告非常重要,这样您才能控制成本,并有望获得盈利的广告系列。

尽管决定每次点击价格的具体过程被严密保密且受多种因素影响,但核心思想是:您的广告越相关,点击成本就越低。

如何设置搜索广告系列

在设置广告系列之前,您通常会先制定预算、挑选关键词并查看竞争情况。同时,您要确保落地页没有问题。然后,您可以设置广告系列:撰写第一条广告、完善其细节,并设置转化跟踪。本教程主要涵盖基于不同落地页来生成大量关键词和广告的流程。

不过,在开始之前,让我们先看看搜索广告系列到底是什么!

广告组

要启动搜索广告系列,您首先需要为广告组制定计划。广告组是组织的基本单元,在这里您将关键词、广告和落地页进行映射。但这三者究竟是什么?

  1. 关键词:用户的意图,即他们在寻找什么。
  2. 广告:您对该意图向用户做出的承诺。
  3. 落地页:您兑现承诺的地方。

正确映射这三个要素大约占工作量的 70-80%。如果这一步做得好,后续维护和调整就会容易得多。

这意味着,为了对用户更具体、更相关,您需要推广自己拥有的产品,核心是通过合适的信息或预期,将合适的人送到合适的页面。一个好的广告系列结构会反映并遵循网站的结构,而网站结构本质上反映了业务战略。

注意 每个广告组都必须属于某个广告系列。在广告系列层级,您可以设置适用于该系列内所有广告组的参数,如语言定向、地域、设备、投放时间等。

搜索广告系列,分步进行

上一节中,您从宏观层面了解了搜索广告系列:看到关键词、广告和落地页属于同一个广告组,并需要为这个组织基本单元制定计划,以使这三者的映射能够反映您的业务战略。本节将更深入地探讨搭建广告系列可以做些什么,重点关注您在本教程中将经历的步骤。

Search Engine Marketing Campaigns Data Science

如上所示,这是您希望实现的映射。最终,您希望得到两个主要的 DataFrame:一个用于关键词,另一个用于广告。如下所示是它们可能的样子。

CampaignAd GroupKeyword
campaign 1adgroup 1keyword 1
campaign 1adgroup 2keyword 2
campaign 2adgroup 1keyword 3
campaign 2adgroup 1keyword 4
campaign 2adgroup 2keyword 5
CampaignAd GroupDisplay URLFinal URLHeadline 1Headline 2
campaign 1adgroup 1datacamp.comdatacamp.com/aHeadline 1Headline 1a
campaign 1adgroup 2datacamp.comdatacamp.com/bHeadline 1Headline 1a
campaign 2adgroup 1datacamp.comdatacamp.com/cHeadline 1Headline 1a
campaign 2adgroup 2datacamp.comdatacamp.com/dHeadline 2Headline 2a
campaign 2adgroup 3datacamp.comdatacamp.com/eHeadline 3Headline 1a

完成这些之后,您就可以将它们以逗号分隔值(CSV)文件的形式上传到 Google AdWords,或其他工作方式完全相同的平台。除了 Bing Ads、Yandex、百度等平台之外,Google AdWords 仍是搜索营销人员使用最广泛的付费搜索平台。

注意 如果您要将数据导入 Google Adwords 或 Bing Ads 之外的平台,则需要做一些小调整!

业务案例:DataCamp

如引言所述,您希望为 DataCamp 创建搜索广告系列。观察人们表达对该公司产品(即数据科学教育)兴趣的不同方式,您很容易就能列出一份初步清单:

  1. 讲师:“Hadley Wickham course”“courses by Garrett Grolemund”等。
  2. 技术:“python course”“r courses”“sql data science course”等。
  3. 课程:我们已有的具体课程名称;“unsupervised learning in python”“deep learning in python”等。
  4. 主题:“machine learning courses”“data visualization course”等。
  5. 软件包/库:“learn ggplot”“matplotlib tutorial”等。

在本教程中,您不会经历传统的关键词研究阶段,因为您可以借助编程语言的力量生成所有可能的组合,并将它们分组到相应的广告系列和广告组中。

因此,要完成此设置,您需要了解两件主要的事情:

  • 产品知识:了解 DataCamp 拥有哪些课程和主题、它们在网站上的组织方式以及分组方式。您可以通过浏览获取这些信息,如果有内部信息(尤其是有计划中的变更!),洞察会更深入。
  • 相关关键词:人们可能用来表达对您所提供内容的兴趣的所有可能方式。就 DataCamp 而言,即“course”“learn”“education”“tutorial”等。您可以通过头脑风暴、使用关键词工具等方法来完成。

为您的 SEM 广告系列生成关键词

让我们从生成关键词开始!

1. 生成讲师关键词

此广告系列将定位搜索 DataCamp 任一讲师课程的人群。

您可以将关键词限定在“course by <instructor name>”,也可以选择更广泛的关键词集,仅定位讲师姓名。起步阶段,最好将目标锁定在带有“course”或“courses”的姓名上,观察效果如何。

您还需要检查所拥有的姓名中,是否有与其他名人同名或非常常见的姓名,然后需要对该讲师的关键词进行收紧。

先获取讲师姓名及其各自的 URL:

import requests
from bs4 import BeautifulSoup


instructors_page = 'https://www.datacamp.com/instructors?all=true'
instructor_link_selector = '.instructor-block__description .instructor-block__link' # CSS class of the link
instructor_name_selector = '.mb-sm'  # CSS class of the name

instructor_resp = requests.get(instructors_page)
soup = BeautifulSoup(instructor_resp.text, 'lxml')

instructor_urls = [url['href'] for url in soup.select(instructor_link_selector)]
instructor_names = [name.text.strip() for name in soup.select(instructor_name_selector)]
instructor_urls = ['https://www.datacamp.com' + url for url in instructor_urls]

将它们保存到一个 DataFrame,供稍后使用。URL 之后将用于生成广告。

instructor_df = pd.DataFrame({
    'name': instructor_names,
    'url': instructor_urls
})
print(instructor_df.shape)
instructor_df.head()
(72, 2)
 nameurl
0Filip Schouwenaarshttps://www.datacamp.com/instructors/filipsch
1Jonathan Cornelissenhttps://www.datacamp.com/instructors/jonathana...
2Hugo Bowne-Andersonhttps://www.datacamp.com/instructors/hugobowne
3Greg Wilsonhttps://www.datacamp.com/instructors/greg48f64...
4Nick Carchedihttps://www.datacamp.com/instructors/nickyc


现在您已经有了讲师姓名,将使用一个模板,将每个姓名与一组与主题相关的关键词组合,主题主要是该讲师的课程。

下面代码中使用的变量:

col_names:这是最终将上传至 Google AdWords 的表格标题列表。
words:将与讲师姓名组合以生成完整关键词/短语的词。
match_types:更多详情请参阅AdWords 帮助中心,这里先介绍基础概念。
[data science course]、"data science course" 和 data science course 在技术上是三种不同的关键词。

  • 完全匹配(方括号)仅在用户搜索与该关键词完全相同的词组时触发广告,例如完全按此书写的“data science course”。
  • 词组匹配(带引号)会在用户搜索该精确字串,且其前后带有任何词时触发您的广告。因此“best data science course”或“data science course online”都会触发我们的广告。
  • 广泛匹配(无标点)会在用户搜索与“data science course”相似或相关的任何内容时触发我们的广告。这取决于 Google 的算法,需谨慎使用,因为它可能在有人搜索“data science platform”时触发广告,而这并非我们要推广的内容。我更喜欢使用“改良广泛匹配”,因为它会进一步收紧定向。它的含义基本上是当有人搜索该词的任意派生形式,而非意义相近的其他词时才会触发。其记号是在词前加“+”。因此,“+game”会被“gaming”“gamers”触发,但不会被“play”触发。
col_names = ['Campaign', 'Ad Group', 'Keyword', 'Criterion Type']
instructor_keywords = []

words = ['course', 'courses', 'learn', 'data science', 'data camp', 'datacamp']
match_types = ['Exact', 'Phrase', 'Broad']
for instructor in instructor_df['name']:
    for word in words:
        for match in match_types:
            if match == 'Broad':
                keyword = '+' + ' +'.join([instructor.replace(' ', ' +').lower(), word])  # modified broach match
            else:
                keyword = instructor.lower() + ' ' + word
            row = ['SEM_Instructors',  # campaign name
                   instructor,  # ad group name
                   keyword, # instructor <keyword>
                   match]  # keyword match type
            instructor_keywords.append(row)

# do the same by having the keywords come before the instructor name
for instructor in instructor_df['name']:
    for word in words:
        for match in match_types:
            if match == 'Broad':
                keyword = '+' + ' +'.join([word, instructor.replace(' ', ' +').lower()])
            else:
                keyword = word + ' ' + instructor.lower() 
            row = ['SEM_Instructors',  # campaign name
                   instructor,  # ad group name
                   keyword, # <keyword> instructor 
                   match]  # keyword match type
            instructor_keywords.append(row)


instructor_keywords_df = pd.DataFrame.from_records(instructor_keywords, 
                                                   columns=col_names)
print('total keywords:', instructor_keywords_df.shape[0])
instructor_keywords_df.head()
total keywords: 2592
 CampaignAd GroupKeywordCriterion Type
0SEM_InstructorsFilip Schouwenaarsfilip schouwenaars courseExact
1SEM_InstructorsFilip Schouwenaarsfilip schouwenaars coursePhrase
2SEM_InstructorsFilip Schouwenaars+filip +schouwenaars +courseBroad
3SEM_InstructorsFilip Schouwenaarsfilip schouwenaars coursesExact
4SEM_InstructorsFilip Schouwenaarsfilip schouwenaars coursesPhrase


基本上,您在遍历讲师姓名、不同关键词以及所有匹配类型,以获得所有可能的组合。我们做了两遍,一次是“讲师姓名 + 关键词”的模板,另一次是“关键词 + 讲师姓名”。

现在,您只需对所有分段重复上述过程,仅在关键词和数据提取方式上做少量修改。

我从R for Data Science学到一个很好的准则:如果您需要复制粘贴超过两次,那就该写个函数了!

def generate_keywords(topics, keywords, match_types=['Exact', 'Phrase', 'Broad'],
                     campaign='SEM_Campaign'):
    col_names = ['Campaign', 'Ad Group', 'Keyword', 'Criterion Type']
    campaign_keywords = []

    for topic in topics:
        for word in keywords:
            for match in match_types:
                if match == 'Broad':
                    keyword = '+' + ' +'.join([topic.lower().replace(' ', ' +'), word.replace(' ', ' +')])
                else:
                    keyword = topic.lower() + ' ' + word
                row = [campaign,  # campaign name
                       topic,  # ad group name
                       keyword, # instructor <keyword>
                       match]  # keyword match type
                campaign_keywords.append(row)

    # I said more than twice! :)             
    for topic in topics:
        for word in keywords:
            for match in match_types:
                if match == 'Broad':
                    keyword = '+' + ' +'.join([word.replace(' ', ' +'), topic.lower().replace(' ', ' +')])
                else:
                    keyword = word + ' ' + topic.lower()
                row = [campaign,  # campaign name
                       topic,  # ad group name
                       keyword, # <keyword> instructor
                       match]  # keyword match type
                campaign_keywords.append(row)

    return pd.DataFrame.from_records(campaign_keywords, columns=col_names)

来试一下:

topics = ['Data Science', 'Machine Learning']
keywords = ['course', 'tutorial']
generate_keywords(topics, keywords).head(10)
 CampaignAd GroupKeywordCriterion Type
0SEM_CampaignData Sciencedata science courseExact
1SEM_CampaignData Sciencedata science coursePhrase
2SEM_CampaignData Science+data +science +courseBroad
3SEM_CampaignData Sciencedata science tutorialExact
4SEM_CampaignData Sciencedata science tutorialPhrase
5SEM_CampaignData Science+data +science +tutorialBroad
6SEM_CampaignMachine Learningmachine learning courseExact
7SEM_CampaignMachine Learningmachine learning coursePhrase
8SEM_CampaignMachine Learning+machine +learning +courseBroad
9SEM_CampaignMachine Learningmachine learning tutorialExact


看起来不错。现在让我们为每个分段生成相应的主题和关键词!

2. 技术类关键词

topics = ['R', 'Python', 'SQL', 'Git', 'Shell']  # listed on the /courses page
keywords = ['data science', 'programming', 'analytics', 'data analysis', 'machine learning',
            'deep learning', 'financial analysis', 'data viz', 'visualization', 'data visualization',
            'learn', 'course', 'courses', 'education', 'data import', 'data cleaning', 
            'data manipulation', 'probability', 'stats', 'statistics', 'course', 'courses',
           'learn', 'education', 'tutorial']  # @marketing_team: this list can / should be refined or 
                                              # expanded based on the strategy and how specific the 
                                              # targeting needs to be
tech_keywords = generate_keywords(topics, keywords, campaign='SEM_Technologies')
print('total keywords:', tech_keywords.shape[0])
tech_keywords.head()
total keywords: 750
 CampaignAd GroupKeywordCriterion Type
0SEM_TechnologiesRr data scienceExact
1SEM_TechnologiesRr data sciencePhrase
2SEM_TechnologiesR+r +data +scienceBroad
3SEM_TechnologiesRr programmingExact
4SEM_TechnologiesRr programmingPhrase

3. 生成课程关键词

这可能是最具体、因此也是最相关的人群定位分段。如果有人搜索“data visualization with r”,而 DataCamp 正好有这门课程,那么广告会极其相关,因为您会有一个精准满足该用户需求的落地页。

不过有个小问题。有些课程名称并不符合用户通常的搜索方式:“Machine Learning with the Experts: School Budgets”“Sentiment Analysis in R: The Tidy Way”。这些并不是糟糕的课程名,但在选择人们可能用于搜索它们的合适关键词时,需要多加留意。

再次像讲师广告系列那样,您可以抓取课程名称及其对应的 URL:

courses_page = 'https://www.datacamp.com/courses/all'
course_link_selector = '.courses__explore-list .course-block'

course_resp = requests.get(courses_page)
soup = BeautifulSoup(course_resp.text, 'lxml')

course_urls = [link.contents[1]['href'] for link in soup.select(course_link_selector)] 
course_urls = ['https://www.datacamp.com' + url for url in course_urls]
course_names = [link.h4.text for link in soup.select(course_link_selector)]
course_df = pd.DataFrame({
    'name': course_names,
    'url': course_urls
})
course_df['name_clean'] = course_df.name.str.replace('\(.*\)', '').str.strip()  # remove (part x)
print('total keywords:', course_df.shape[0])
course_df.head()
total keywords: 104
 nameurlname_clean
0Intro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...Intro to Python for Data Science
1Introduction to Rhttps://www.datacamp.com/courses/free-introduction-to-r...Introduction to R
2Intermediate Python for Data Sciencehttps://www.datacamp.com/courses/intermediate-python...Intermediate Python for Data Science
3Introduction to Git for Data Sciencehttps://www.datacamp.com/courses/introduction-to-git...Introduction to Git for Data Science
4Intermediate Rhttps://www.datacamp.com/courses/intermediate-rIntermediate R


课程也将使用相同的方法(调用 generate_keywords() 函数),但需要谨慎,如上所述,部分课程名并不是人们会去搜索的表达,需要逐一审查。以下设置足以起步,之后您可以查看数据并做出决策。

请注意,下面使用空字符并非错误。课程名称本身足够冗长且具体,适合作为关键词本身,而无需添加“learn”“course”等限定词。因此,您将同时使用仅包含课程名的关键词,以及加入限定词的组合。

keywords = ['', 'learn', 'course', 'courses', 'tutorial', 'education']
course_keywords = generate_keywords(course_df['name_clean'], keywords, campaign='SEM_Courses')
print('total keywords:', course_keywords.shape[0])
course_keywords.head(10)
total keywords: 3744
 CampaignAd GroupKeywordCriterion Type
0SEM_CoursesIntro to Python for Data Scienceintro to python for data scienceExact
1SEM_CoursesIntro to Python for Data Scienceintro to python for data sciencePhrase
2SEM_CoursesIntro to Python for Data Science+intro +to +python +for +data +science +Broad
3SEM_CoursesIntro to Python for Data Scienceintro to python for data science learnExact
4SEM_CoursesIntro to Python for Data Scienceintro to python for data science learnPhrase
5SEM_CoursesIntro to Python for Data Science+intro +to +python +for +data +science +learnBroad
6SEM_CoursesIntro to Python for Data Scienceintro to python for data science courseExact
7SEM_CoursesIntro to Python for Data Scienceintro to python for data science coursePhrase
8SEM_CoursesIntro to Python for Data Science+intro +to +python +for +data +science +courseBroad
9SEM_CoursesIntro to Python for Data Scienceintro to python for data science coursesExact

4. 主题类关键词

这些基本上是大众感兴趣的通用主题。它们对应“学习路径(tracks)”版块,包含技能和职业两个子版块。就您的目的而言,可以将它们归为同一广告系列。流程仍与前面各节相同!

技能

skills_page = 'https://www.datacamp.com/tracks/skill'
skills_link_selector = '#all .shim'

skills_resp = requests.get(skills_page)
skill_soup = BeautifulSoup(skills_resp.text, 'lxml')

skills_urls = [link['href'] for link in skill_soup.select(skills_link_selector)] 
skills_names = [skill.replace('/tracks/', '').replace('-', ' ') for skill in skills_urls]
skills_urls = ['https://www.datacamp.com' + url for url in skills_urls]

职业

career_page = 'https://www.datacamp.com/tracks/career'
career_link_selector = '#all .shim'

career_resp = requests.get(career_page)
career_soup = BeautifulSoup(career_resp.text, 'lxml')

career_urls = [link['href'] for link in career_soup.select(career_link_selector)] 

career_names = [career.replace('/tracks/', '').replace('-', ' ') for career in career_urls]
career_urls = ['https://www.datacamp.com' + url for url in career_urls]
tracks_df = pd.DataFrame({
    'name': skills_names + career_names,
    'url': skills_urls + career_urls
})
tracks_df['name'] = [x.title() for x in tracks_df['name']]
tracks_df.head()
tracks_keywords = generate_keywords(tracks_df['name'], keywords, campaign='SEM_Tracks')
print('total keywords:', tracks_keywords.shape[0])
tracks_keywords.head()
total keywords: 720
 CampaignAd GroupKeywordCriterion Type
0SEM_TracksR Programmingr programmingExact
1SEM_TracksR Programmingr programmingPhrase
2SEM_TracksR Programming+r +programming +Broad
3SEM_TracksR Programmingr programming learnExact
4SEM_TracksR Programmingr programming learnPhrase

最后,将 instructor_keywords、tech_keywords、course_keywords 和 tracks_keywords 中的所有关键词连接起来,汇总到一个大的 DataFrame 中:

full_keywords_df = pd.concat([instructor_keywords_df, tech_keywords, course_keywords, tracks_keywords])
print('total keywords:', full_keywords_df.shape[0])
print('total campaigns:', len(set(full_keywords_df['Campaign'])))
print('total ad groups:', len(set(full_keywords_df['Ad Group'])))
full_keywords_df.to_csv('keywords.csv', index=False)
full_keywords_df.head()
total keywords: 7806
total campaigns: 4
total ad groups: 191
 CampaignAd GroupKeywordCriterion Type
0SEM_InstructorsFilip Schouwenaarsfilip schouwenaars courseExact
1SEM_InstructorsFilip Schouwenaarsfilip schouwenaars coursePhrase
2SEM_InstructorsFilip Schouwenaars+filip +schouwenaars +courseBroad
3SEM_InstructorsFilip Schouwenaarsfilip schouwenaars coursesExact
4SEM_InstructorsFilip Schouwenaarsfilip schouwenaars coursesPhrase

现在您已经可以使用这些关键词了!如果想查看完整数据集,请点击这里。接下来,您需要为每个广告组生成广告。

让我们来生成广告。

广告生成与文案撰写

您目前已有如下内容:

  • 在 full_keywords_df DataFrame 中,广告系列与广告组名称已正确映射
  • 广告组名称及其对应的 URL(来自先前对课程、讲师与学习路径的抓取),还需要为技术类生成一个

有了这些,您可以按照以下计划进行:

  1. 创建可用的广告模板(建议先从 2-3 个开始)
  2. 在('name'、'url')DataFrame 中创建并添加 Campaign 列
  3. 将所有('name'、'url')DataFrame 合并为一个大的 DataFrame
  4. 为所有广告组生成全部广告;每条广告包含以下字段(这些将是您正在处理的同一 DataFrame 中的新列):

    • Headline 1:最多 30 个字符
    • Headline 2:最多 30 个字符
    • Display URL:根据最终 URL 自动推断
    • Final URL:用户最终到达的完整路径(必须与展示 URL 属于同一域名)
  5. 确保与 keywords DataFrame 保持一致

  6. 上传并启动广告系列!

生成广告的过程,就是把主题名称(课程、技术、讲师等)替换到模板中相应位置,并为您拥有的每个广告组制作 2-3 个广告变体。

Python SEM Campaign

广告模板

需要注意的是,虽然将广告组名称填入相应位置的过程很直接,但问题在于您需要让各字段的长度不超过上述限制。由于课程和主题名称差异很大,您需要想办法应对。

让我们看看问题有多大:

%matplotlib inline
import matplotlib.pyplot as plt
adgroup_lengths = pd.Series([len(adgrp) for adgrp in full_keywords_df['Ad Group'].unique()])
long_adgroups = sum(adgroup_lengths > 30)
plt.figure(figsize=(9,6))
plt.hist(adgroup_lengths, rwidth=0.9, bins=50)
plt.vlines(x=30, ymin=0, ymax=10, colors='red')
plt.title(str(long_adgroups) + ' ad group name lenghts > 30 (don\'t fit in a headline)',  fontsize=17)
plt.xlabel('Ad Group Name Lengths', fontsize=15)
plt.ylabel('Count', fontsize=15)
plt.yticks(range(11))
plt.xticks(range(0, 51, 5))
plt.grid(alpha=0.5)
plt.show()

Search Engine Marketing Data Science Python

看来这个问题并不轻松,也没有简单直接的解决办法。理想情况下,我们希望在两个标题中包含我们所推广产品(课程)的完整标题。

我想过不同的应对方式,决定写一个简单的算法,将名称拆分为两个短语,每个不超过三十个字符。

该算法并不适合通用场景,需要稍作调整才能通用,但对于本数据集已经足够好用:

def split_string(string, splits=2, max_len=60):
    """Split `string` into `splits` words, each shorter than `max_len` / `splits`"""
    if len(string) < max_len / splits:
        return string, ''
    str_words = string.split(' ')
    result = ''
    for i, word in enumerate(str_words):
        if len(result + ' ' + word) <= max_len / splits:
            result += word + ' '
        else:
            break
    spaces = result.strip().count(' ')
    result2 = string[string[len(result):].index(word) + len(result):]
    return result.strip(), result2
print(split_string('this is a very long course name that needs splitting', 2, 60))
print(split_string('short course name', 2, 60))
('this is a very long course', 'name that needs splitting')
('short course name', '')

我平时不常这样做,但我喜欢这种技巧,觉得在创建其他广告系列时也会用到。这是编写教程的一个意外收获!

现在我们来思考要写的模板。

我常用的通用广告模板包含以下要素(通常按此顺序):

  • 产品:如果我在 Google 搜索“data science course”,我需要在链接/广告中某处看到“data science course”。
  • 收益:这是人们在完成课程之外真正追求的情感/心理层面的东西,“提升职业发展”“脱颖而出”。
  • 特性:既然你给了我美好愿景,那就告诉我如何实现!“100+ 门数据科学课程”“跟顶尖专家学习”“获得代码技能的即时反馈”。
  • 行动号召:你说了你拥有什么,激发了我购买欲,也展示了实现路径。我被说服了。现在我该做什么?“注册免费试用”“免费体验首章内容”“年度订阅立省 20%”

要把这些全部塞进一条类似推文长度的广告并不容易,而且部分内容可能会重叠。但我们会尽力而为。

  • Headline 1:始终包含课程名称(或其前半部分)。
  • Headline 2:课程名称的后半部分,或以下之一:
    • Boost Your Data Science Career
    • Stand Out From the Crowd
    • Tackle Complex Questions
  • Description:每个广告组将包含以下三种变体并轮播。
    • Learn Directly From the Top Experts in the Field. 20% off Annual Subscriptions
    • Get Ahead of the Curve, Master Data Science Skills. $29 / Month. Cancel Anytime
    • Choose From a Wide Variety of Topics Tuaght by the Best in the World. Start Now

创建 Campaign 列

full_keywords_df.Campaign.unique()  # just to make sure you have consistent naming conventions
array(['SEM_Instructors', 'SEM_Technologies', 'SEM_Courses', 'SEM_Tracks'], dtype=object)
course_df['Campaign'] = 'SEM_Courses'
course_df = course_df.rename(columns={'name_clean': 'name', 'name': 'old_name'})
course_df.head()
 old_nameurlnameCampaign
0Intro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...Intro to Python for Data ScienceSEM_Courses
1Introduction to Rhttps://www.datacamp.com/courses/free-introduction-to-r...Introduction to RSEM_Courses
2Intermediate Python for Data Sciencehttps://www.datacamp.com/courses/intermediate-python...Intermediate Python for Data ScienceSEM_Courses
3Introduction to Git for Data Sciencehttps://www.datacamp.com/courses/introduction-to-git...Introduction to Git for Data ScienceSEM_Courses
4Intermediate Rhttps://www.datacamp.com/courses/intermediate-rIntermediate RSEM_Courses
instructor_df['Campaign'] = 'SEM_Instructors'
instructor_df.head()
 nameurlCampaign
0Filip Schouwenaarshttps://www.datacamp.com/instructors/filipschSEM_Instructors
1Jonathan Cornelissenhttps://www.datacamp.com/instructors/jonathana...SEM_Instructors
2Hugo Bowne-Andersonhttps://www.datacamp.com/instructors/hugobowneSEM_Instructors
3Greg Wilsonhttps://www.datacamp.com/instructors/greg48f64...SEM_Instructors
4Nick Carchedihttps://www.datacamp.com/instructors/nickycSEM_Instructors
tracks_df['Campaign'] = 'SEM_Tracks'
tracks_df.head()
 nameurlCampaign
0R Programminghttps://www.datacamp.com/tracks/r-programmingSEM_Tracks
1Importing Cleaning Data With Rhttps://www.datacamp.com/tracks/importing-cleaning-data-with-r...SEM_Tracks
2Data Manipulation With Rhttps://www.datacamp.com/tracks/data-manipulation-with-r...SEM_Tracks
3Python Programminghttps://www.datacamp.com/tracks/python-programming...SEM_Tracks
4Importing Cleaning Data With Pythonhttps://www.datacamp.com/tracks/importing-cleaning-data-with-python...SEM_Tracks
tech_domain = 'https://www.datacamp.com/courses/tech:'
tech_domain_list = []
for tech in ['R', 'Python', 'SQL', 'Git', 'Shell']:
    tech_domain_list.append((tech, tech_domain + tech))
tech_df = pd.DataFrame.from_records(tech_domain_list, columns=['name', 'url'])
tech_df['Campaign'] = 'SEM_Technologies'
tech_df

合并所有('name'、'url')DataFrame

full_ads_df = pd.concat([course_df[['Campaign', 'name', 'url']],
                        instructor_df,
                        tracks_df,
                        tech_df], ignore_index=True)
full_ads_df = full_ads_df.rename(columns={'name': 'Ad Group', 'url': 'Final URL'})
print('total rows:', full_ads_df.shape[0])
n_adgroups = full_ads_df.shape[0]
full_ads_df.head()
total rows: 201
 CampaignAd GroupFinal URL
0SEM_CoursesIntro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...
1SEM_CoursesIntroduction to Rhttps://www.datacamp.com/courses/free-introduction-to-r...
2SEM_CoursesIntermediate Python for Data Sciencehttps://www.datacamp.com/courses/intermediate-python...
3SEM_CoursesIntroduction to Git for Data Sciencehttps://www.datacamp.com/courses/introduction-to-git...
4SEM_CoursesIntermediate Rhttps://www.datacamp.com/courses/intermediate-r

生成广告

简单回顾一下当前进度。您现在有了包含 Campaign、Ad Group 和 Final URL 列并正确映射的广告 DataFrame。接下来需要添加 Headline 1、Headline 2 和 Description 字段。

请记住,您将为每个广告组添加三种不同的广告变体。这主要是为了测试目的,以观察用户点击情况、哪些广告的转化更高等。最终,DataFrame 的行数应为当前的三倍。

我们先在 full_ads_df 中将每一行复制三遍:

full_ads_df = full_ads_df.iloc[[x  for x in range(n_adgroups) for i in range(3)], :] 
print('total rows:', full_ads_df.shape[0])
full_ads_df.head(9)
total rows: 603
 CampaignAd GroupFinal URL
0SEM_CoursesIntro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...
0SEM_CoursesIntro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...
0SEM_CoursesIntro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...
1SEM_CoursesIntroduction to Rhttps://www.datacamp.com/courses/free-introduction-to-r...
1SEM_CoursesIntroduction to Rhttps://www.datacamp.com/courses/free-introduction-to-r...
1SEM_CoursesIntroduction to Rhttps://www.datacamp.com/courses/free-introduction-to-r...
2SEM_CoursesIntermediate Python for Data Sciencehttps://www.datacamp.com/courses/intermediate-python...
2SEM_CoursesIntermediate Python for Data Sciencehttps://www.datacamp.com/courses/intermediate-python...
2SEM_CoursesIntermediate Python for Data Sciencehttps://www.datacamp.com/courses/intermediate-python...


现在添加上面创建的三种不同的 Description。

Description = [
    'Learn Directly From the Top Experts in the Field. 20% off Annual Subcriptions',
    'Be Ahead of the Curve, Master Data Science Skills. $29 / Month. Cancel Anytime',
    'Choose From a Wide Variety of Topics Tuaght by the Best in the World. Start Now'   
]
Description = [x for i in range(n_adgroups) for x in Description ]
full_ads_df['Description'] = Description
full_ads_df.head()
 CampaignAd GroupFinal URLDescription
0SEM_CoursesIntro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...Learn Directly From the Top Experts in the Fie...
0SEM_CoursesIntro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...Be Ahead of the Curve, Master Data Science Ski...
0SEM_CoursesIntro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...Choose From a Wide Variety of Topics Tuaght by...
1SEM_CoursesIntroduction to Rhttps://www.datacamp.com/courses/free-introduction-to-r...Learn Directly From the Top Experts in the Fie...
1SEM_CoursesIntroduction to Rhttps://www.datacamp.com/courses/free-introduction-to-r...Be Ahead of the Curve, Master Data Science Ski...


接着,向 DataFrame 添加 Headline 1 和 Headline 2。您就快完成了!

benefits = [
    'Boost Your Data Science Career',
    'Stand Out From the Crowd',
    'Tackle Complex Questions'    
]

当广告组名称长度不超过 30 时,收益语将作为 Headline 2 填入。在这种情况下,您会有空白字段,我们将用上述收益语之一填充。

benefits = [x for i in range(n_adgroups) for x in benefits]
headlines = [split_string(x) for x in full_ads_df['Ad Group']]
full_ads_df['Headline 1'] = [x[0] for x in headlines]
full_ads_df['Headline 2'] = [x[1] if x[1] else benefits[i] for i, x in enumerate(headlines)]
print('total ads:', full_ads_df.shape[0])
full_ads_df.head(9)
total ads: 603
 CampaignAd GroupFinal URLDescriptionHeadline 1Headline 2
0SEM_CoursesIntro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...Learn Directly From the Top Experts in the Fie...Intro to Python for DataScience
0SEM_CoursesIntro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...Be Ahead of the Curve, Master Data Science Ski...Intro to Python for DataScience
0SEM_CoursesIntro to Python for Data Sciencehttps://www.datacamp.com/courses/intro-to-python-for-data-science...Choose From a Wide Variety of Topics Tuaght by...Intro to Python for DataScience
1SEM_CoursesIntroduction to Rhttps://www.datacamp.com/courses/free-introduction-to-r...Learn Directly From the Top Experts in the Fie...Introduction to RBoost Your Data Science Career
1SEM_CoursesIntroduction to Rhttps://www.datacamp.com/courses/free-introduction-to-r...Be Ahead of the Curve, Master Data Science Ski...Introduction to RStand Out From the Crowd
1SEM_CoursesIntroduction to Rhttps://www.datacamp.com/courses/free-introduction-to-r...Choose From a Wide Variety of Topics Tuaght by...Introduction to RTackle Complex Questions
2SEM_CoursesIntermediate Python for Data Sciencehttps://www.datacamp.com/courses/intermediate-python...Learn Directly From the Top Experts in the Fie...Intermediate Python for DataScience
2SEM_CoursesIntermediate Python for Data Sciencehttps://www.datacamp.com/courses/intermediate-python...Be Ahead of the Curve, Master Data Science Ski...Intermediate Python for DataScience
2SEM_CoursesIntermediate Python for Data Sciencehttps://www.datacamp.com/courses/intermediate-python...Choose From a Wide Variety of Topics Tuaght by...Intermediate Python for DataScience


如您所见,“Intro to Python for Data Science” 足够长,需要拆成两个字段,因此我们按原样保留以确保清晰。而“Introduction to R” 能放入第一个标题,于是我们在 Headline 2 中插入了三种不同的收益语。

大功告成!

仔细检查细节

做个快速检查,确保两个 DataFrame 中的广告系列与广告组名称一致。

ads_check = (full_ads_df[['Campaign', 'Ad Group']]
             .drop_duplicates()
             .sort_values(['Campaign', 'Ad Group'])
             .reset_index(drop=True))
keywords_check = (full_keywords_df[['Campaign', 'Ad Group']]
                  .drop_duplicates()
                  .sort_values(['Campaign', 'Ad Group'])
                  .reset_index(drop=True))

all(ads_check == keywords_check)
True
full_ads_df.to_csv('ads.csv', index=False)

上传并启动

如前所述,本教程只涵盖了 SEM 广告系列中的特定步骤,因此需要您对搜索引擎营销的运作有基本了解。如果您想进一步了解上传和启动广告组的机制和细节,可以查看 AdWords 入门指南。若想系统学习不同领域的完整课程,可以访问 Google Academy for Ads。

数据科学与 SEM:还有更多可探索!

现在有了这两个 CSV 文件,您即可上传并开始投放广告系列。您还需要设置每日预算、地域定向以及其他一些参数,但大体而言,已经可以出发了。

如需查看 CSV 文件,请见:

希望本教程对您有所帮助。感谢阅读!如果您愿意分享借助 Python 完成的增长项目,欢迎在 Twitter 上联系我 @eliasdabbas。

主题