Curso
Como usuario intensivo de DataCamp desde hace dos años, he aprendido muchísimo. Mi actividad principal es el marketing online y me he beneficiado mucho de las habilidades de ciencia de datos que he adquirido. Ahora puedo gestionar campañas mucho más grandes y complejas, y mantenerlas de forma eficiente. Como ya estoy bastante familiarizado con el contenido, los distintos temas y los packages de R y Python, pensé en cómo podría crear campañas de búsqueda para DataCamp, simplemente como ejercicio.
En este tutorial, abordarás los siguientes temas:
- Primero aprenderás más sobre el Search Engine Marketing (SEM) y las campañas de búsqueda;
- Después, analizarás con más detalle el caso de negocio;
- A continuación, generarás palabras clave para el profesorado, las tecnologías, los cursos y los temas de DataCamp.
- Con las palabras clave en la mano, podrás empezar a generar tus anuncios. Primero definirás una estrategia y luego crearás plantillas de anuncios.
Search Engine Marketing (SEM) y campañas
¿Qué es el SEM?
El SEM es una de las formas más efectivas de hacer crecer tu negocio en un mercado cada vez más competitivo. Consiste en atraer tráfico a tu web comprando anuncios en los motores de búsqueda. Google AdWords es una de las formas más populares de publicidad online: pujas por aparecer en los enlaces patrocinados del buscador para palabras clave relacionadas con tu negocio y pagas una tarifa por cada clic.
Pagar por clic puede suponer un coste importante, por lo que es clave planificar y agrupar bien tus palabras clave y anuncios para controlar el gasto y, con suerte, lograr campañas rentables.
Aunque el proceso exacto para determinar el precio por clic es un secreto bien guardado y depende de muchos factores, la idea principal es que cuanto más relevantes sean tus anuncios, menor será tu coste por clic.
Cómo configurar una campaña de búsqueda
Antes de montar una campaña, normalmente defines un presupuesto, eliges palabras clave y estudias a la competencia. Además, te aseguras de que tu landing page esté preparada. Luego ya puedes configurar la campaña: redactas tu primer anuncio, ajustas sus detalles y configuras el seguimiento de conversiones. Este tutorial se centra sobre todo en el proceso de generar un gran volumen de palabras clave y anuncios en función de las distintas páginas de destino que tengamos.
Pero antes de empezar, ¡veamos exactamente qué son estas campañas de búsqueda!
Grupos de anuncios
Para empezar con una campaña de búsqueda, primero necesitas definir un plan para tus grupos de anuncios. Este es el elemento básico de organización donde asignas palabras clave, anuncios y páginas de destino. ¿Qué son exactamente estos tres componentes?
- Palabras clave: la intención del usuario, lo que está buscando.
- Anuncios: tu promesa al usuario para esa intención.
- Páginas de destino: el cumplimiento de esa promesa.
Mapear correctamente estos tres elementos es alrededor del 70-80% del trabajo. Si lo haces bien, el mantenimiento y los cambios serán mucho más sencillos.
Esto implica que, para ser específico y relevante para los usuarios, debes promocionar el producto que tienes y centrarte en llevar a la persona adecuada a la página adecuada con el mensaje o la expectativa adecuados. Una buena estructura de campaña refleja y sigue la estructura del sitio web, que en el fondo refleja la estrategia de negocio.
Nota: cada grupo de anuncios debe formar parte de una campaña. A nivel de campaña tienes ajustes que afectan a todos los grupos de anuncios, como la segmentación por idioma, ubicaciones, dispositivos, franja horaria, etc.
Campaña de búsqueda, paso a paso
En la sección anterior viste las campañas de búsqueda a alto nivel: palabras clave, anuncios y páginas de destino forman un grupo de anuncios, y necesitas un plan para esta unidad básica donde asignas esos tres componentes de forma que reflejen tu estrategia. En esta sección, profundizarás en cómo configurar una campaña, centrándote en los pasos que recorrerás en este tutorial.

Como ves arriba, este es el mapeo que quieres conseguir. Como salida, querrás terminar con dos DataFrames principales: uno para palabras clave y otro para anuncios. Abajo puedes ver un ejemplo de cómo se verían.
| Campaign | Ad Group | Keyword |
|---|---|---|
| campaign 1 | adgroup 1 | keyword 1 |
| campaign 1 | adgroup 2 | keyword 2 |
| campaign 2 | adgroup 1 | keyword 3 |
| campaign 2 | adgroup 1 | keyword 4 |
| campaign 2 | adgroup 2 | keyword 5 |
| Campaign | Ad Group | Display URL | Final URL | Headline 1 | Headline 2 |
|---|---|---|---|---|---|
| campaign 1 | adgroup 1 | datacamp.com | datacamp.com/a | Headline 1 | Headline 1a |
| campaign 1 | adgroup 2 | datacamp.com | datacamp.com/b | Headline 1 | Headline 1a |
| campaign 2 | adgroup 1 | datacamp.com | datacamp.com/c | Headline 1 | Headline 1a |
| campaign 2 | adgroup 2 | datacamp.com | datacamp.com/d | Headline 2 | Headline 2a |
| campaign 2 | adgroup 3 | datacamp.com | datacamp.com/e | Headline 3 | Headline 1a |
Una vez listo, podrás subirlos como archivos CSV (valores separados por comas) a Google AdWords o incluso a otras plataformas que funcionan de forma muy similar. Google AdWords es, con diferencia, la plataforma de búsqueda de pago más popular entre los especialistas en search, además de Bing Ads, Yandex, Baidu, y otras.
Nota: si quieres importar tus datos a otras plataformas y no a Google Adwords o Bing Ads, ¡tendrás que hacer pequeños ajustes!
El caso de negocio: DataCamp
Como leíste en la introducción, quieres crear campañas de búsqueda para DataCamp. Si analizas las distintas formas en que alguien puede mostrar interés por el producto que ofrece esta empresa, es decir, formación en ciencia de datos, puedes elaborar fácilmente una lista inicial de posibilidades:
- Instructores: "curso de Hadley Wickham", "cursos de Garrett Grolemund", etc.
- Tecnologías: "curso de python", "cursos de r", "curso de sql para ciencia de datos", etc.
- Cursos: nombres de cursos específicos que tenemos; "unsupervised learning in python", "deep learning in python", etc.
- Temas: "cursos de machine learning", "curso de visualización de datos", etc.
- Packages/librerías: "aprender ggplot", "tutorial de matplotlib", etc.
En este tutorial no pasarás por la fase tradicional de investigación de palabras clave porque tienes el poder del lenguaje de programación para generar todas las combinaciones posibles y agruparlas en sus respectivas campañas y grupos de anuncios.
Por tanto, necesitas dos cosas principales para hacer esta configuración:
- Conocimiento del producto: saber qué cursos y temas tiene DataCamp, cómo se organizan en la web y cómo se agrupan. Puedes descubrirlo navegando por el sitio y, sin duda, obtener mejores insights con información interna (¡especialmente si hay cambios previstos!).
- Palabras clave relevantes: todas las posibles formas en que alguien puede expresar deseo por lo que ofreces. En el caso de DataCamp: "curso", "aprender", "formación", "tutorial", etc. Puedes hacerlo con lluvia de ideas, usando herramientas de keywords y otros métodos.
Generación de palabras clave para tu campaña de SEM
¡Empecemos generando las palabras clave!
1. Generar palabras clave de instructores
Esta campaña se dirigirá a personas que busquen cursos de cualquiera de los instructores de DataCamp.
Puedes restringir las palabras clave a "course by <instructor name>" o apostar por un conjunto amplio que apunte solo al nombre del instructor. Al principio es mejor orientar los nombres con "course" o "courses" y ver el efecto.
También tendrás que comprobar si alguno de los nombres coincide con el de otra persona famosa o es muy común; en ese caso, tendrás que restringir las palabras clave para ese instructor.
Empiezas obteniendo los nombres de los instructores y las URLs de cada uno:
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]
Los guardas en un DataFrame para usarlos más adelante. Las URLs se usarán después para generar los anuncios.
instructor_df = pd.DataFrame({
'name': instructor_names,
'url': instructor_urls
})
print(instructor_df.shape)
instructor_df.head()
(72, 2)
| name | url | |
|---|---|---|
| 0 | Filip Schouwenaars | https://www.datacamp.com/instructors/filipsch |
| 1 | Jonathan Cornelissen | https://www.datacamp.com/instructors/jonathana... |
| 2 | Hugo Bowne-Anderson | https://www.datacamp.com/instructors/hugobowne |
| 3 | Greg Wilson | https://www.datacamp.com/instructors/greg48f64... |
| 4 | Nick Carchedi | https://www.datacamp.com/instructors/nickyc |
Ahora que ya tienes los nombres de los instructores, usarás una plantilla en la que combinas cada nombre con un conjunto de palabras clave relacionadas con tu tema, que en esencia son cursos del instructor.
Variables usadas en el siguiente código:
col_names: lista de nombres de cabecera de la tabla que subiremos a Google AdWords.words: palabras que combinarás con los nombres de los instructores para generar palabras/frases clave completas.match_types: puedes ver más detalles en el Centro de ayuda de AdWords, pero aquí tienes lo básico.
[data science course], "data science course" y data science course son técnicamente tres palabras clave distintas.
- exact match (entre corchetes) solo mostrará anuncios si el usuario busca exactamente esa palabra clave, por ejemplo, 'data science course', escrita tal cual.
- phrase match (con comillas) mostrará tus anuncios si el usuario busca la cadena exacta junto con cualquier cosa antes o después. Por tanto, "best data science course" o "data science course online" activarían tus anuncios.
- broad match (sin signos) activará tus anuncios si alguien busca algo similar o relacionado con 'data science course'. Esto depende de los algoritmos de Google y hay que tener cuidado, porque podría activar anuncios con búsquedas como 'data science platform', que no es exactamente lo que queremos promocionar. A mí me gusta más el broad match modificado, porque restringe un poco más la segmentación. Básicamente activa los anuncios si alguien busca cualquier derivado de la palabra, no sinónimos en significado. Se indica con un signo '+' al principio de la palabra. Así, '+game' activaría anuncios con 'gaming', 'gamers', pero no con '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
| Campaign | Ad Group | Keyword | Criterion Type | |
|---|---|---|---|---|
| 0 | SEM_Instructors | Filip Schouwenaars | filip schouwenaars course | Exact |
| 1 | SEM_Instructors | Filip Schouwenaars | filip schouwenaars course | Phrase |
| 2 | SEM_Instructors | Filip Schouwenaars | +filip +schouwenaars +course | Broad |
| 3 | SEM_Instructors | Filip Schouwenaars | filip schouwenaars courses | Exact |
| 4 | SEM_Instructors | Filip Schouwenaars | filip schouwenaars courses | Phrase |
Básicamente, estás iterando sobre los nombres de los instructores, todas las palabras clave y todos los tipos de concordancia para obtener todas las combinaciones posibles. Lo hacemos dos veces: una con la plantilla 'nombre del instructor + palabra clave' y otra con 'palabra clave + nombre del instructor'.
Ahora simplemente repites lo mismo para todos nuestros segmentos con pequeñas modificaciones en las palabras clave y en cómo extraemos los datos.
Una buena regla que aprendí de R for Data Science es que si vas a copiar y pegar más de dos veces, ¡es hora de escribir una función!
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)
Probémosla:
topics = ['Data Science', 'Machine Learning']
keywords = ['course', 'tutorial']
generate_keywords(topics, keywords).head(10)
| Campaign | Ad Group | Keyword | Criterion Type | |
|---|---|---|---|---|
| 0 | SEM_Campaign | Data Science | data science course | Exact |
| 1 | SEM_Campaign | Data Science | data science course | Phrase |
| 2 | SEM_Campaign | Data Science | +data +science +course | Broad |
| 3 | SEM_Campaign | Data Science | data science tutorial | Exact |
| 4 | SEM_Campaign | Data Science | data science tutorial | Phrase |
| 5 | SEM_Campaign | Data Science | +data +science +tutorial | Broad |
| 6 | SEM_Campaign | Machine Learning | machine learning course | Exact |
| 7 | SEM_Campaign | Machine Learning | machine learning course | Phrase |
| 8 | SEM_Campaign | Machine Learning | +machine +learning +course | Broad |
| 9 | SEM_Campaign | Machine Learning | machine learning tutorial | Exact |
Tiene buena pinta. ¡Ahora generemos los temas y palabras clave relevantes para cada segmento!
2. Palabras clave de tecnologías
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
| Campaign | Ad Group | Keyword | Criterion Type | |
|---|---|---|---|---|
| 0 | SEM_Technologies | R | r data science | Exact |
| 1 | SEM_Technologies | R | r data science | Phrase |
| 2 | SEM_Technologies | R | +r +data +science | Broad |
| 3 | SEM_Technologies | R | r programming | Exact |
| 4 | SEM_Technologies | R | r programming | Phrase |
3. Generar palabras clave de cursos
Probablemente sea el segmento más específico y, por tanto, el más relevante para llegar a la gente. Si alguien busca "data visualization with r" y DataCamp tiene ese curso, el anuncio será extremadamente relevante porque tendrás la landing page exacta que satisface esa necesidad.
Hay un pequeño problema. Algunos nombres de cursos no coinciden con lo que un usuario buscaría típicamente: "Machine Learning with the Experts: School Budgets", "Sentiment Analysis in R: The Tidy Way". No son malos nombres, pero habrá que prestar atención para seleccionar las palabras clave adecuadas que la gente podría usar para encontrarlos.
De nuevo, puedes hacer scraping de los nombres y sus URLs como hiciste con la campaña de instructores:
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
| name | url | name_clean | |
|---|---|---|---|
| 0 | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... | Intro to Python for Data Science |
| 1 | Introduction to R | https://www.datacamp.com/courses/free-introduction-to-r... | Introduction to R |
| 2 | Intermediate Python for Data Science | https://www.datacamp.com/courses/intermediate-python... | Intermediate Python for Data Science |
| 3 | Introduction to Git for Data Science | https://www.datacamp.com/courses/introduction-to-git... | Introduction to Git for Data Science |
| 4 | Intermediate R | https://www.datacamp.com/courses/intermediate-r | Intermediate R |
Harás lo mismo (usar la función generate_keywords()) para los cursos, pero con cuidado, porque hay que revisarlos: como se dijo arriba, algunos nombres no son realmente lo que la gente buscaría, y tendrás que tratarlos caso por caso. Lo siguiente es un buen punto de partida; luego podrás ver los datos y decidir.
Ten en cuenta que usar el carácter vacío abajo no es un error. Los nombres de los cursos son lo suficientemente largos y específicos como para funcionar como palabras clave en sí mismos, sin añadir calificadores como 'learn' o 'course'. Así que usarás los nombres solos y también junto con palabras calificadoras.
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
| Campaign | Ad Group | Keyword | Criterion Type | |
|---|---|---|---|---|
| 0 | SEM_Courses | Intro to Python for Data Science | intro to python for data science | Exact |
| 1 | SEM_Courses | Intro to Python for Data Science | intro to python for data science | Phrase |
| 2 | SEM_Courses | Intro to Python for Data Science | +intro +to +python +for +data +science + | Broad |
| 3 | SEM_Courses | Intro to Python for Data Science | intro to python for data science learn | Exact |
| 4 | SEM_Courses | Intro to Python for Data Science | intro to python for data science learn | Phrase |
| 5 | SEM_Courses | Intro to Python for Data Science | +intro +to +python +for +data +science +learn | Broad |
| 6 | SEM_Courses | Intro to Python for Data Science | intro to python for data science course | Exact |
| 7 | SEM_Courses | Intro to Python for Data Science | intro to python for data science course | Phrase |
| 8 | SEM_Courses | Intro to Python for Data Science | +intro +to +python +for +data +science +course | Broad |
| 9 | SEM_Courses | Intro to Python for Data Science | intro to python for data science courses | Exact |
4. Palabras clave por temas
Son temas genéricos que la gente puede buscar. Los cubre la sección de "tracks", con skills y career como subsecciones. Para tu propósito, puedes agruparlos en la misma campaña. El proceso es el mismo que en secciones anteriores.
Skills
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]
Careers
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()
| name | url | |
|---|---|---|
| 0 | R Programming | https://www.datacamp.com/tracks/r-programming |
| 1 | Importing Cleaning Data With R | https://www.datacamp.com/tracks/importing-cleaning-data-with-r... |
| 2 | Data Manipulation With R | https://www.datacamp.com/tracks/data-manipulation-with-r... |
| 3 | Python Programming | https://www.datacamp.com/tracks/python-programming... |
| 4 | Importing Cleaning Data With Python | https://www.datacamp.com/tracks/importing-cleaning-data-with-python... |
tracks_keywords = generate_keywords(tracks_df['name'], keywords, campaign='SEM_Tracks')
print('total keywords:', tracks_keywords.shape[0])
tracks_keywords.head()
total keywords: 720
| Campaign | Ad Group | Keyword | Criterion Type | |
|---|---|---|---|---|
| 0 | SEM_Tracks | R Programming | r programming | Exact |
| 1 | SEM_Tracks | R Programming | r programming | Phrase |
| 2 | SEM_Tracks | R Programming | +r +programming + | Broad |
| 3 | SEM_Tracks | R Programming | r programming learn | Exact |
| 4 | SEM_Tracks | R Programming | r programming learn | Phrase |
Por último, concatena todas las palabras clave listadas en instructor_keywords, tech_keywords, course_keywords y tracks_keywords para tenerlo todo en un único 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
| Campaign | Ad Group | Keyword | Criterion Type | |
|---|---|---|---|---|
| 0 | SEM_Instructors | Filip Schouwenaars | filip schouwenaars course | Exact |
| 1 | SEM_Instructors | Filip Schouwenaars | filip schouwenaars course | Phrase |
| 2 | SEM_Instructors | Filip Schouwenaars | +filip +schouwenaars +course | Broad |
| 3 | SEM_Instructors | Filip Schouwenaars | filip schouwenaars courses | Exact |
| 4 | SEM_Instructors | Filip Schouwenaars | filip schouwenaars courses | Phrase |
¡Ya estás listo con tus palabras clave! Si quieres ver el conjunto de datos completo, descárgalo aquí. Después, necesitas generar anuncios para cada grupo de anuncios.
Vamos a generar los anuncios.
Generación de anuncios y copywriting
Actualmente tienes lo siguiente:
- Campañas y nombres de grupos de anuncios correctamente mapeados entre sí en el DataFrame
full_keywords_df - El nombre del grupo de anuncios y la URL correspondiente del scraping previo (cursos, instructores y tracks), y necesitas generar uno para tecnologías.
Con esto, puedes seguir este plan:
- Crea plantillas de anuncios (con 2-3 para empezar es suficiente)
- Crea una columna
Campaigny añádela a los DataFrames ('name','url') - Une todos los DataFrames (
'name','url') en uno solo -
Genera todos los anuncios para todos los grupos de anuncios; cada anuncio tendrá estos campos (nuevas columnas en el mismo DataFrame):
- Headline 1: máximo 30 caracteres
- Headline 2: máximo 30 caracteres
- Display URL: se infiere automáticamente de la Final URL
- Final URL: la ruta completa a la que llegará el usuario (debe ser del mismo dominio que la Display URL)
-
Asegúrate de que el trabajo es coherente con el DataFrame de
keywords - ¡Sube y lanza las campañas!
Generar anuncios significa sustituir el nombre del tema (curso, tecnología, instructor, etc.) donde corresponda en la plantilla y crear 2-3 variaciones por cada grupo de anuncios.

Plantillas de anuncios
Un detalle importante: aunque insertar los nombres de los grupos de anuncios donde toca es sencillo, el problema es que los campos deben respetar los límites de longitud. Y como los nombres de cursos y temas varían bastante, hay que ver cómo manejarlo.
Veamos hasta qué punto es un problema:
%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()

Parece que no es un problema trivial y no hay una solución directa. Idealmente, nos gustaría que los dos titulares contuvieran el título completo del producto (curso) que estamos promocionando.
Pensé en distintas opciones y decidí escribir un algoritmo sencillo que divide el nombre en dos frases, cada una con un máximo de treinta caracteres.
El algoritmo no es apto para uso general y necesita retoques para generalizarlo, pero funciona suficientemente bien para este conjunto de datos:
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', '')
No es algo que suela hacer, pero me gusta esta técnica y creo que la usaré al crear otras campañas. ¡Una agradable consecuencia de escribir un tutorial!
Ahora pensemos en las plantillas que quieres redactar.
La plantilla general que uso suele incluir estos elementos (normalmente en este orden).
- Producto: si busco 'data science course' en Google, necesito ver 'data science course' en los enlaces/anuncios de alguna manera.
- Beneficios: el impulso emocional/psicológico que la gente busca más allá de completar el curso: "impulsa tu carrera", "destaca frente a los demás".
- Características: ahora que me has prometido la luna, ¡enséñame cómo vas a llevarme allí! "más de 100 cursos de ciencia de datos", "aprende con los mejores expertos", "recibe feedback instantáneo sobre tu código".
- Llamada a la acción: bien, ya me has dicho qué ofreces, me has motivado y me has mostrado cómo voy a lograrlo. Me convence. ¿Qué hago ahora? "regístrate y prueba gratis", "prueba los primeros capítulos gratis", "ahorra un 20% en suscripciones anuales"
No es fácil meter todo en un anuncio de la longitud de un tuit, y algunos puntos se solapan. Pero haremos lo posible.
- Headline 1: siempre contendrá el nombre del curso (o su primera mitad).
- Headline 2: la segunda mitad del nombre del curso, o una de estas opciones:
- Boost Your Data Science Career
- Stand Out From the Crowd
- Tackle Complex Questions
- Description: cada grupo de anuncios tendrá estas tres variaciones en rotación.
- 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
Crear columnas 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_name | url | name | Campaign | |
|---|---|---|---|---|
| 0 | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... | Intro to Python for Data Science | SEM_Courses |
| 1 | Introduction to R | https://www.datacamp.com/courses/free-introduction-to-r... | Introduction to R | SEM_Courses |
| 2 | Intermediate Python for Data Science | https://www.datacamp.com/courses/intermediate-python... | Intermediate Python for Data Science | SEM_Courses |
| 3 | Introduction to Git for Data Science | https://www.datacamp.com/courses/introduction-to-git... | Introduction to Git for Data Science | SEM_Courses |
| 4 | Intermediate R | https://www.datacamp.com/courses/intermediate-r | Intermediate R | SEM_Courses |
instructor_df['Campaign'] = 'SEM_Instructors'
instructor_df.head()
| name | url | Campaign | |
|---|---|---|---|
| 0 | Filip Schouwenaars | https://www.datacamp.com/instructors/filipsch | SEM_Instructors |
| 1 | Jonathan Cornelissen | https://www.datacamp.com/instructors/jonathana... | SEM_Instructors |
| 2 | Hugo Bowne-Anderson | https://www.datacamp.com/instructors/hugobowne | SEM_Instructors |
| 3 | Greg Wilson | https://www.datacamp.com/instructors/greg48f64... | SEM_Instructors |
| 4 | Nick Carchedi | https://www.datacamp.com/instructors/nickyc | SEM_Instructors |
tracks_df['Campaign'] = 'SEM_Tracks'
tracks_df.head()
| name | url | Campaign | |
|---|---|---|---|
| 0 | R Programming | https://www.datacamp.com/tracks/r-programming | SEM_Tracks |
| 1 | Importing Cleaning Data With R | https://www.datacamp.com/tracks/importing-cleaning-data-with-r... | SEM_Tracks |
| 2 | Data Manipulation With R | https://www.datacamp.com/tracks/data-manipulation-with-r... | SEM_Tracks |
| 3 | Python Programming | https://www.datacamp.com/tracks/python-programming... | SEM_Tracks |
| 4 | Importing Cleaning Data With Python | https://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 | Campaign | |
|---|---|---|---|
| 0 | R | https://www.datacamp.com/category/r | SEM_Technologies |
| 1 | Python | https://www.datacamp.com/category/python | SEM_Technologies |
| 2 | SQL | https://www.datacamp.com/category/sql | SEM_Technologies |
| 3 | Git | https://www.datacamp.com/courses/tech:Git | SEM_Technologies |
| 4 | Shell | https://www.datacamp.com/category/shell | SEM_Technologies |
Unir todos los DataFrames ('name', 'url')
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
| Campaign | Ad Group | Final URL | |
|---|---|---|---|
| 0 | SEM_Courses | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... |
| 1 | SEM_Courses | Introduction to R | https://www.datacamp.com/courses/free-introduction-to-r... |
| 2 | SEM_Courses | Intermediate Python for Data Science | https://www.datacamp.com/courses/intermediate-python... |
| 3 | SEM_Courses | Introduction to Git for Data Science | https://www.datacamp.com/courses/introduction-to-git... |
| 4 | SEM_Courses | Intermediate R | https://www.datacamp.com/courses/intermediate-r |
Generar anuncios
Para situarnos: ya tienes el DataFrame de anuncios con las columnas Campaign, Ad Group y Final URL correctamente mapeadas. Falta añadir Headline 1, Headline 2 y Description.
Recuerda que para cada grupo de anuncios añadirás tres variaciones distintas. Es una buena práctica para hacer tests: ver en qué hace clic la gente, qué anuncios convierten mejor, etc. Deberías terminar con un DataFrame con el triple de filas.
Empecemos duplicando cada fila tres veces en 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
| Campaign | Ad Group | Final URL | |
|---|---|---|---|
| 0 | SEM_Courses | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... |
| 0 | SEM_Courses | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... |
| 0 | SEM_Courses | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... |
| 1 | SEM_Courses | Introduction to R | https://www.datacamp.com/courses/free-introduction-to-r... |
| 1 | SEM_Courses | Introduction to R | https://www.datacamp.com/courses/free-introduction-to-r... |
| 1 | SEM_Courses | Introduction to R | https://www.datacamp.com/courses/free-introduction-to-r... |
| 2 | SEM_Courses | Intermediate Python for Data Science | https://www.datacamp.com/courses/intermediate-python... |
| 2 | SEM_Courses | Intermediate Python for Data Science | https://www.datacamp.com/courses/intermediate-python... |
| 2 | SEM_Courses | Intermediate Python for Data Science | https://www.datacamp.com/courses/intermediate-python... |
Ahora añade las tres descripciones que creaste arriba.
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()
| Campaign | Ad Group | Final URL | Description | |
|---|---|---|---|---|
| 0 | SEM_Courses | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... | Learn Directly From the Top Experts in the Fie... |
| 0 | SEM_Courses | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... | Be Ahead of the Curve, Master Data Science Ski... |
| 0 | SEM_Courses | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... | Choose From a Wide Variety of Topics Tuaght by... |
| 1 | SEM_Courses | Introduction to R | https://www.datacamp.com/courses/free-introduction-to-r... | Learn Directly From the Top Experts in the Fie... |
| 1 | SEM_Courses | Introduction to R | https://www.datacamp.com/courses/free-introduction-to-r... | Be Ahead of the Curve, Master Data Science Ski... |
Después, añade Headline 1 y Headline 2 al DataFrame. ¡Ya casi está!
benefits = [
'Boost Your Data Science Career',
'Stand Out From the Crowd',
'Tackle Complex Questions'
]
Los beneficios se incluirán como Headline 2 cuando la longitud del nombre del grupo de anuncios sea de 30 o menos. En ese caso quedaría un campo vacío que rellenaremos con uno de los beneficios.
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
| Campaign | Ad Group | Final URL | Description | Headline 1 | Headline 2 | |
|---|---|---|---|---|---|---|
| 0 | SEM_Courses | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... | Learn Directly From the Top Experts in the Fie... | Intro to Python for Data | Science |
| 0 | SEM_Courses | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... | Be Ahead of the Curve, Master Data Science Ski... | Intro to Python for Data | Science |
| 0 | SEM_Courses | Intro to Python for Data Science | https://www.datacamp.com/courses/intro-to-python-for-data-science... | Choose From a Wide Variety of Topics Tuaght by... | Intro to Python for Data | Science |
| 1 | SEM_Courses | Introduction to R | https://www.datacamp.com/courses/free-introduction-to-r... | Learn Directly From the Top Experts in the Fie... | Introduction to R | Boost Your Data Science Career |
| 1 | SEM_Courses | Introduction to R | https://www.datacamp.com/courses/free-introduction-to-r... | Be Ahead of the Curve, Master Data Science Ski... | Introduction to R | Stand Out From the Crowd |
| 1 | SEM_Courses | Introduction to R | https://www.datacamp.com/courses/free-introduction-to-r... | Choose From a Wide Variety of Topics Tuaght by... | Introduction to R | Tackle Complex Questions |
| 2 | SEM_Courses | Intermediate Python for Data Science | https://www.datacamp.com/courses/intermediate-python... | Learn Directly From the Top Experts in the Fie... | Intermediate Python for Data | Science |
| 2 | SEM_Courses | Intermediate Python for Data Science | https://www.datacamp.com/courses/intermediate-python... | Be Ahead of the Curve, Master Data Science Ski... | Intermediate Python for Data | Science |
| 2 | SEM_Courses | Intermediate Python for Data Science | https://www.datacamp.com/courses/intermediate-python... | Choose From a Wide Variety of Topics Tuaght by... | Intermediate Python for Data | Science |
Como ves, "Intro to Python for Data Science" era lo bastante largo como para ocupar dos campos, así que lo dejamos tal cual para mantener la claridad. En el segundo caso, "Introduction to R" cabe en el primer titular, así que insertamos los tres beneficios en Headline 2.
¡Y listo!
Revisa bien los detalles
Una comprobación rápida para asegurarte de que todos los nombres de campaña y de grupo de anuncios en ambos DataFrames coinciden.
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)
Sube y lanza
Como hemos comentado, este tutorial solo cubre pasos concretos dentro de campañas SEM y por tanto requiere una comprensión básica de cómo funciona el search engine marketing. Si quieres saber más sobre la mecánica y los detalles para subir y lanzar tus grupos de anuncios, puedes consultar la guía de AdWords para empezar. Para acceder a cursos completos en distintas áreas, puedes visitar la Google Academy for Ads.
Ciencia de datos y SEM: ¡queda mucho por descubrir!
Con los dos archivos CSV que tienes ahora, puedes subirlos y empezar a ejecutar tus campañas. Tendrás que definir presupuestos diarios, geosegmentación y algunos otros parámetros, pero en esencia ya lo tienes todo listo.
Si quieres consultar los CSV, los encontrarás aquí:
Espero que te haya resultado útil. Gracias por leerlo y, si quieres compartir algún proyecto de crecimiento que hayas hecho con Python, no dudes en escribirme en Twitter @eliasdabbas.
