Accéder au contenu principal

La data science au service du Search Engine Marketing (SEM)

Dans ce tutoriel, la data science rencontre le Search Engine Marketing : apprenez à créer des campagnes Google AdWords en générant des mots-clés et des modèles d’annonces avec Python !
Actualisé 19 sept. 2026  · 15 min lire

Explorer avec l’IA

ChatGPTClaudePerplexity

Utilisateur assidu de DataCamp depuis deux ans, j’ai énormément appris. Mon cœur de métier est le marketing en ligne et les compétences en data science acquises m’ont beaucoup servi. Je peux désormais gérer des campagnes bien plus vastes et complexes, et les optimiser efficacement. Comme je maîtrise désormais le contenu, les thématiques et les packages en R et en Python, j’ai envisagé, à titre d’exercice, de créer des campagnes search pour DataCamp.

\n

Dans ce tutoriel, vous aborderez les sujets suivants :

\n
    \n
  • Vous commencerez par un rappel sur le Search Engine Marketing (SEM) et les campagnes search ;
  • \n
  • Vous étudierez ensuite le cas d’usage ;
  • \n
  • Puis vous générerez des mots-clés pour les instructeurs, les technologies, les cours et les thématiques de DataCamp.
  • \n
  • Une fois les mots-clés prêts, vous pourrez générer vos annonces. Vous définirez d’abord une stratégie, puis vous créerez des modèles d’annonces.
  • \n
\n

Search Engine Marketing (SEM) et campagnes

\n

Qu’est-ce que le SEM ?

\n

Le SEM est l’un des moyens les plus efficaces pour développer votre activité sur un marché de plus en plus concurrentiel. Il consiste à acquérir du trafic sur votre site en achetant des annonces sur les moteurs de recherche. Google AdWords est l’un des formats de publicité en ligne les plus populaires : vous enchérissez pour apparaître dans les liens sponsorisés d’un moteur de recherche sur des mots-clés liés à votre activité, puis vous payez un coût par clic au moteur.

\n

Payer au clic peut vite coûter cher : il est donc essentiel de planifier et regrouper vos mots-clés et annonces de façon à maîtriser vos coûts et, idéalement, à rendre vos campagnes rentables.

\n

Bien que le calcul exact du prix par clic soit confidentiel et dépende de nombreux facteurs, l’idée principale est que plus vos annonces sont pertinentes, plus votre coût par clic diminue.

\n

Configurer une campagne search

\n

Avant de lancer une campagne, vous définissez généralement un budget, sélectionnez des mots-clés et analysez la concurrence. Vous vérifiez également que votre page d’atterrissage est prête. Ensuite, vous pouvez paramétrer votre campagne : rédiger une première annonce, ajuster ses paramètres puis configurer le suivi des conversions. Ce tutoriel se concentre surtout sur la génération à grande échelle de mots-clés et d’annonces, à partir des différentes pages d’atterrissage disponibles.

\n

Mais avant de commencer, voyons précisément ce que sont ces campagnes search !

\n

Groupes d’annonces

\n

Pour démarrer, vous devez d’abord concevoir un plan pour vos groupes d’annonces. C’est l’unité de base où vous associez mots-clés, annonces et pages d’atterrissage. Mais que recouvrent exactement ces trois éléments ?

\n
    \n
  1. Mots-clés : l’intention de l’utilisateur, ce qu’il recherche.
  2. \n
  3. Annonces : votre promesse en réponse à cette intention.
  4. \n
  5. Pages d’atterrissage : la concrétisation de cette promesse.
  6. \n
\n

Bien cartographier ces trois éléments représente environ 70 à 80 % du travail. Si vous le faites correctement, la maintenance et les ajustements deviennent bien plus simples.

\n

Concrètement, pour être spécifique et pertinent, vous devez promouvoir le bon produit et, surtout, diriger la bonne personne vers la bonne page avec le bon message ou la bonne promesse. Une structure de campagne efficace reflète la structure du site, qui elle-même traduit la stratégie business.

\n

Remarque : chaque groupe d’annonces appartient à une campagne. Au niveau de la campagne, vous gérez des paramètres communs à tous les groupes d’annonces, comme le ciblage linguistique, la zone géographique, les appareils, les horaires, etc.

\n

Campagne search, étape par étape

\n

Dans la section précédente, vous avez pris de la hauteur : vous avez vu que les mots-clés, les annonces et les pages d’atterrissage composent un groupe d’annonces, et que vous devez élaborer un plan pour cette unité d’organisation afin qu’elle reflète votre stratégie. Ici, vous allez entrer dans le détail opérationnel des étapes suivies dans ce tutoriel.

\n

\"Search

\n

Comme illustré ci-dessus, c’est cette cartographie que vous visez. En sortie, vous souhaitez obtenir deux DataFrames principaux : l’un pour les mots-clés et l’autre pour les annonces. Voici à quoi cela peut ressembler.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
CampaignAd GroupKeyword
campaign 1adgroup 1keyword 1
campaign 1adgroup 2keyword 2
campaign 2adgroup 1keyword 3
campaign 2adgroup 1keyword 4
campaign 2adgroup 2keyword 5
\n
\n\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
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
\n
\n

Une fois ces fichiers prêts, vous pouvez les importer au format CSV (valeurs séparées par des virgules) dans Google AdWords ou d’autres plateformes fonctionnant de façon similaire. Google AdWords est de loin la plateforme d’achat de mots-clés la plus utilisée par les spécialistes du search, aux côtés de Bing Ads, Yandex, Baidu, etc.

\n

Remarque : si vous importez vos données dans d’autres plateformes que Google Adwords ou Bing Ads, de légers ajustements seront nécessaires.

\n

Le cas d’usage : DataCamp

\n

Comme indiqué en introduction, vous allez créer des campagnes search pour DataCamp. En examinant les différentes manières dont une personne peut exprimer un intérêt pour l’offre de l’entreprise, à savoir la formation en data science, vous pouvez aisément dresser une première liste :

\n
    \n
  1. Instructeurs : \"Hadley Wickham course\", \"courses by Garrett Grolemund\", etc.
  2. \n
  3. Technologies : \"python course\", \"r courses\", \"sql data science course\", etc.
  4. \n
  5. Cours : noms de cours spécifiques disponibles ; \"unsupervised learning in python\", \"deep learning in python\", etc.
  6. \n
  7. Thématiques : \"machine learning courses\", \"data visualization course\", etc.
  8. \n
  9. Packages/bibliothèques : \"learn ggplot\", \"matplotlib tutorial\", etc.
  10. \n
\n

Dans ce tutoriel, vous ne passerez pas par la phase traditionnelle de recherche de mots-clés, car la puissance du langage de programmation vous permet de générer toutes les combinaisons possibles et de les regrouper dans leurs campagnes et groupes d’annonces respectifs.

\n

Vous avez donc besoin de deux éléments clés pour cette configuration :

\n
    \n
  • Connaissance produit : savoir quels cours et thématiques DataCamp propose, comment ils sont organisés sur le site et groupés. Vous pouvez l’identifier en explorant le site, et affiner grâce à des informations internes (notamment en cas d’évolutions prévues).
  • \n
  • Mots-clés pertinents : toutes les manières possibles d’exprimer un intérêt pour ce que vous offrez. Dans le cas de DataCamp : \"course\", \"learn\", \"education\", \"tutorial\", etc. À obtenir via brainstorming, outils de mots-clés et autres méthodes.
  • \n
\n

Générer les mots-clés pour votre campagne SEM

\n

Commençons par générer les mots-clés !

\n

1. Générer des mots-clés par instructeur

\n

Cette campagne cible les personnes qui recherchent des cours d’un instructeur DataCamp en particulier.

\n

Vous pouvez restreindre les mots-clés à \"course by <instructor name>\" ou viser des variantes plus larges autour du nom de l’instructeur seul. Au départ, il est préférable d’associer les noms à \"course\" ou \"courses\" et d’observer la performance.

\n

Vérifiez également si l’un des noms correspond à une célébrité ou à un nom très commun : vous devrez alors restreindre les mots-clés pour cet instructeur.

\n

Commencez par récupérer les noms des instructeurs et leurs URLs :

\n
import requests\nfrom bs4 import BeautifulSoup\n\n\ninstructors_page = 'https://www.datacamp.com/instructors?all=true'\ninstructor_link_selector = '.instructor-block__description .instructor-block__link' # CSS class of the link\ninstructor_name_selector = '.mb-sm'  # CSS class of the name\n\ninstructor_resp = requests.get(instructors_page)\nsoup = BeautifulSoup(instructor_resp.text, 'lxml')\n\ninstructor_urls = [url['href'] for url in soup.select(instructor_link_selector)]\ninstructor_names = [name.text.strip() for name in soup.select(instructor_name_selector)]\ninstructor_urls = ['https://www.datacamp.com' + url for url in instructor_urls]\n
\n

Placez-les dans un DataFrame pour les réutiliser plus tard. Les URLs serviront ensuite à générer les annonces.

\n
instructor_df = pd.DataFrame({\n    'name': instructor_names,\n    'url': instructor_urls\n})\nprint(instructor_df.shape)\ninstructor_df.head()\n
\n
(72, 2)\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n


Maintenant que vous avez les noms des instructeurs, vous allez utiliser un modèle qui combine chaque nom avec un ensemble de mots-clés liés au sujet, à savoir des cours par instructeur.

\n

Variables utilisées dans le code ci-dessous :

\n

col_names : liste des en-têtes de la table que vous importerez dans Google AdWords.
words : les mots que vous combinerez avec les noms des instructeurs pour générer les requêtes complètes.
match_types : plus de détails sur le centre d’aide AdWords, mais voici l’essentiel.
[data science course], \"data science course\" et data science course sont techniquement trois mots-clés différents.

\n
    \n
  • Exact match (entre crochets) : l’annonce ne se déclenche que si l’utilisateur saisit exactement ce mot-clé, par exemple \"data science course\" écrit tel quel.
  • \n
  • Phrase match (entre guillemets) : l’annonce se déclenche si l’utilisateur recherche la chaîne exacte précédée ou suivie d’autres termes. Ainsi \"best data science course\" ou \"data science course online\" déclencheront l’annonce.
  • \n
  • Broad match (sans ponctuation) : l’annonce peut se déclencher sur des termes proches ou associés à \"data science course\". C’est laissé aux algorithmes de Google et il faut rester vigilant, car une recherche comme \"data science platform\" pourrait déclencher l’annonce alors que ce n’est pas l’offre visée. Je préfère le broad match modifié, qui restreint davantage le ciblage. Il déclenche l’annonce si un dérivé du mot est présent, et non un synonyme. On le note par un signe \"+\" au début du mot. \"+game\" peut ainsi déclencher \"gaming\", \"gamers\" mais pas \"play\".
  • \n
\n
col_names = ['Campaign', 'Ad Group', 'Keyword', 'Criterion Type']\ninstructor_keywords = []\n\nwords = ['course', 'courses', 'learn', 'data science', 'data camp', 'datacamp']\nmatch_types = ['Exact', 'Phrase', 'Broad']\nfor instructor in instructor_df['name']:\n    for word in words:\n        for match in match_types:\n            if match == 'Broad':\n                keyword = '+' + ' +'.join([instructor.replace(' ', ' +').lower(), word])  # modified broach match\n            else:\n                keyword = instructor.lower() + ' ' + word\n            row = ['SEM_Instructors',  # campaign name\n                   instructor,  # ad group name\n                   keyword, # instructor <keyword>\n                   match]  # keyword match type\n            instructor_keywords.append(row)\n\n# do the same by having the keywords come before the instructor name\nfor instructor in instructor_df['name']:\n    for word in words:\n        for match in match_types:\n            if match == 'Broad':\n                keyword = '+' + ' +'.join([word, instructor.replace(' ', ' +').lower()])\n            else:\n                keyword = word + ' ' + instructor.lower() \n            row = ['SEM_Instructors',  # campaign name\n                   instructor,  # ad group name\n                   keyword, # <keyword> instructor \n                   match]  # keyword match type\n            instructor_keywords.append(row)\n\n\ninstructor_keywords_df = pd.DataFrame.from_records(instructor_keywords, \n                                                   columns=col_names)\nprint('total keywords:', instructor_keywords_df.shape[0])\ninstructor_keywords_df.head()\n
\n
total keywords: 2592\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n


Concrètement, vous bouclez sur les noms des instructeurs, les différents mots-clés et les types de correspondance pour générer toutes les combinaisons possibles. Vous le faites deux fois : \"nom de l’instructeur + mot-clé\" puis \"mot-clé + nom de l’instructeur\".

\n

Il suffit ensuite de répéter le procédé pour tous les segments, avec de légères adaptations quant aux mots-clés et à la façon d’extraire les données.

\n

Une bonne règle apprise dans R for Data Science : si vous copiez-collez plus de deux fois, il est temps d’écrire une fonction !

\n
def generate_keywords(topics, keywords, match_types=['Exact', 'Phrase', 'Broad'],\n                     campaign='SEM_Campaign'):\n    col_names = ['Campaign', 'Ad Group', 'Keyword', 'Criterion Type']\n    campaign_keywords = []\n\n    for topic in topics:\n        for word in keywords:\n            for match in match_types:\n                if match == 'Broad':\n                    keyword = '+' + ' +'.join([topic.lower().replace(' ', ' +'), word.replace(' ', ' +')])\n                else:\n                    keyword = topic.lower() + ' ' + word\n                row = [campaign,  # campaign name\n                       topic,  # ad group name\n                       keyword, # instructor <keyword>\n                       match]  # keyword match type\n                campaign_keywords.append(row)\n\n    # I said more than twice! :)             \n    for topic in topics:\n        for word in keywords:\n            for match in match_types:\n                if match == 'Broad':\n                    keyword = '+' + ' +'.join([word.replace(' ', ' +'), topic.lower().replace(' ', ' +')])\n                else:\n                    keyword = word + ' ' + topic.lower()\n                row = [campaign,  # campaign name\n                       topic,  # ad group name\n                       keyword, # <keyword> instructor\n                       match]  # keyword match type\n                campaign_keywords.append(row)\n\n    return pd.DataFrame.from_records(campaign_keywords, columns=col_names)\n
\n

Essayons :

\n
topics = ['Data Science', 'Machine Learning']\nkeywords = ['course', 'tutorial']\ngenerate_keywords(topics, keywords).head(10)\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n


C’est concluant. Générons maintenant les thématiques et mots-clés pertinents pour chacun de vos segments.

\n

2. Mots-clés par technologie

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

3. Générer des mots-clés par cours

\n

C’est sans doute le segment le plus spécifique et donc le plus pertinent pour cibler. Si quelqu’un recherche \"data visualization with r\" et que DataCamp propose ce cours, l’annonce sera extrêmement pertinente, car vous avez la bonne page d’atterrissage répondant exactement au besoin.

\n

Un petit écueil toutefois : certains titres de cours ne correspondent pas à ce que les utilisateurs saisissent typiquement dans la barre de recherche : \"Machine Learning with the Experts: School Budgets\", \"Sentiment Analysis in R: The Tidy Way\". Ces titres ne sont pas mauvais, mais il faudra sélectionner des mots-clés adaptés à ce que les gens recherchent réellement, au cas par cas.

\n

Encore une fois, vous pouvez scraper les noms et URLs comme pour la campagne des instructeurs :

\n
courses_page = 'https://www.datacamp.com/courses/all'\ncourse_link_selector = '.courses__explore-list .course-block'\n\ncourse_resp = requests.get(courses_page)\nsoup = BeautifulSoup(course_resp.text, 'lxml')\n\ncourse_urls = [link.contents[1]['href'] for link in soup.select(course_link_selector)] \ncourse_urls = ['https://www.datacamp.com' + url for url in course_urls]\ncourse_names = [link.h4.text for link in soup.select(course_link_selector)]\n
\n
course_df = pd.DataFrame({\n    'name': course_names,\n    'url': course_urls\n})\ncourse_df['name_clean'] = course_df.name.str.replace('\\(.*\\)', '').str.strip()  # remove (part x)\nprint('total keywords:', course_df.shape[0])\ncourse_df.head()\n
\n
total keywords: 104\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n


Vous allez procéder de même (avec la fonction generate_keywords()) pour les cours, en gardant en tête qu’une relecture s’impose : comme indiqué, certains titres ne correspondent pas aux requêtes usuelles et doivent être traités individuellement. Ce qui suit constitue une bonne base pour démarrer ; vous affinerez ensuite selon les données.

\n

Notez que l’utilisation du caractère vide ci-dessous n’est pas une erreur. Les titres de cours sont suffisamment longs et spécifiques pour servir de mots-clés en eux-mêmes, sans qualificatifs additionnels comme \"learn\" ou \"course\". Vous utiliserez donc les titres seuls, ainsi que des variantes avec qualificatifs.

\n
keywords = ['', 'learn', 'course', 'courses', 'tutorial', 'education']\ncourse_keywords = generate_keywords(course_df['name_clean'], keywords, campaign='SEM_Courses')\nprint('total keywords:', course_keywords.shape[0])\ncourse_keywords.head(10)\n
\n
total keywords: 3744\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n

4. Mots-clés par thématique

\n

Il s’agit de thématiques génériques susceptibles d’intéresser les internautes. Elles sont couvertes par la section \"parcours\" (tracks), déclinée en \"compétences\" et \"carrières\". Pour notre usage, elles peuvent être regroupées dans une même campagne. Le processus est identique à celui des sections précédentes.

\n

Compétences

\n
skills_page = 'https://www.datacamp.com/tracks/skill'\nskills_link_selector = '#all .shim'\n\nskills_resp = requests.get(skills_page)\nskill_soup = BeautifulSoup(skills_resp.text, 'lxml')\n\nskills_urls = [link['href'] for link in skill_soup.select(skills_link_selector)] \nskills_names = [skill.replace('/tracks/', '').replace('-', ' ') for skill in skills_urls]\nskills_urls = ['https://www.datacamp.com' + url for url in skills_urls]\n
\n

Carrières

\n
career_page = 'https://www.datacamp.com/tracks/career'\ncareer_link_selector = '#all .shim'\n\ncareer_resp = requests.get(career_page)\ncareer_soup = BeautifulSoup(career_resp.text, 'lxml')\n\ncareer_urls = [link['href'] for link in career_soup.select(career_link_selector)] \n\ncareer_names = [career.replace('/tracks/', '').replace('-', ' ') for career in career_urls]\ncareer_urls = ['https://www.datacamp.com' + url for url in career_urls]\n
\n
tracks_df = pd.DataFrame({\n    'name': skills_names + career_names,\n    'url': skills_urls + career_urls\n})\ntracks_df['name'] = [x.title() for x in tracks_df['name']]\ntracks_df.head()\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 nameurl
0R Programminghttps://www.datacamp.com/tracks/r-programming
1Importing Cleaning Data With Rhttps://www.datacamp.com/tracks/importing-cleaning-data-with-r...
2Data Manipulation With Rhttps://www.datacamp.com/tracks/data-manipulation-with-r...
3Python Programminghttps://www.datacamp.com/tracks/python-programming...
4Importing Cleaning Data With Pythonhttps://www.datacamp.com/tracks/importing-cleaning-data-with-python...
\n
\n
tracks_keywords = generate_keywords(tracks_df['name'], keywords, campaign='SEM_Tracks')\nprint('total keywords:', tracks_keywords.shape[0])\ntracks_keywords.head()\n
\n
total keywords: 720\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n

Enfin, concaténez tous les mots-clés listés dans instructor_keywords, tech_keywords, course_keywords et tracks_keywords pour les rassembler dans un unique DataFrame :

\n
full_keywords_df = pd.concat([instructor_keywords_df, tech_keywords, course_keywords, tracks_keywords])\nprint('total keywords:', full_keywords_df.shape[0])\nprint('total campaigns:', len(set(full_keywords_df['Campaign'])))\nprint('total ad groups:', len(set(full_keywords_df['Ad Group'])))\nfull_keywords_df.to_csv('keywords.csv', index=False)\nfull_keywords_df.head()\n
\n
total keywords: 7806\ntotal campaigns: 4\ntotal ad groups: 191\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n

Vos mots-clés sont prêts ! Pour consulter l’ensemble du jeu de données, récupérez-le ici. Il vous reste à générer des annonces pour chacun de vos groupes d’annonces.

\n

Passons à la génération d’annonces.

\n

Génération d’annonces et rédaction

\n

À ce stade, vous avez :

\n
    \n
  • Les campagnes et les groupes d’annonces correctement associés dans le DataFrame full_keywords_df
  • \n
  • Le nom du groupe d’annonces et l’URL correspondante issus de votre scraping (cours, instructeurs et parcours) ; il vous reste à générer celui des technologies.
  • \n
\n

Avec ces éléments, suivez le plan suivant :

\n
    \n
  1. Créer des modèles d’annonces (2 à 3 suffisent pour démarrer)
  2. \n
  3. Créer une colonne Campaign et l’ajouter aux DataFrames ('name', 'url')
  4. \n
  5. Fusionner tous les DataFrames ('name', 'url') en un seul
  6. \n
  7. \n

    Générer toutes les annonces pour tous les groupes d’annonces ; chaque annonce comprend les champs suivants (nouvelles colonnes dans le même DataFrame) :

    \n
      \n
    • Headline 1 : 30 caractères maximum
    • \n
    • Headline 2 : 30 caractères maximum
    • \n
    • Display URL : déduite automatiquement de la Final URL
    • \n
    • Final URL : l’URL finale vers laquelle l’utilisateur est redirigé (même domaine que la Display URL)
    • \n
    \n
  8. \n
  9. \n

    Vérifier la cohérence avec le DataFrame keywords

    \n
  10. \n
  11. Importer et lancer les campagnes !
  12. \n
\n

Générer des annonces revient à insérer le nom du sujet (cours, techno, instructeur, etc.) dans le modèle à l’endroit prévu, et à créer 2 à 3 variantes pour chaque groupe d’annonces.

\n

\"Python

\n

Modèles d’annonces

\n

Un point d’attention : même si l’insertion des noms de groupes d’annonces dans les champs est simple, vous devez respecter les limites de longueur. Comme les titres de cours et de thématiques varient fortement, il faut trouver une approche adaptée.

\n

Voyons l’ampleur du problème :

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

\"Search

\n

Le problème n’est pas anodin, et il n’existe pas de solution universelle. Idéalement, les deux titres devraient contenir l’intitulé complet du produit (cours) promu.

\n

Après plusieurs pistes, j’ai opté pour un algorithme simple qui scinde le nom en deux segments ne dépassant pas trente caractères.

\n

L’algorithme n’est pas conçu pour un usage générique et nécessiterait des ajustements, mais il fonctionne suffisamment bien pour ce jeu de données :

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

Ce n’est pas une pratique que j’emploie souvent, mais j’aime cette technique et je pense la réutiliser pour d’autres campagnes. Un bel effet secondaire de la rédaction d’un tutoriel !

\n

Passons aux modèles que vous souhaitez rédiger.

\n

Le modèle d’annonce que j’utilise en général comprend les éléments suivants (dans cet ordre) :

\n
    \n
  • Produit : si je cherche \"data science course\" sur Google, je veux voir \"data science course\" quelque part dans l’annonce.
  • \n
  • Bénéfices : la motivation profonde au-delà du simple fait de terminer le cours : \"boost your career\", \"stand out from the crowd\".
  • \n
  • Caractéristiques : après la promesse, montrez comment vous allez y parvenir : \"over 100 data science courses\", \"learn from top experts\", \"get instant feedback on your coding skills\".
  • \n
  • Appel à l’action : vous m’avez présenté l’offre, motivé, et montré la méthode. Je suis convaincu. Que faire maintenant ? \"sign up for a free trial\", \"sample first chapters for free\", \"save 20% on annual subscriptions\"
  • \n
\n

Il n’est pas simple de tout faire tenir dans une annonce aussi courte, et certains éléments se recoupent. Faites au mieux.

\n
    \n
  • Headline 1 : contiendra toujours le nom du cours (ou sa première moitié).
  • \n
  • Headline 2 : la seconde moitié du nom du cours, ou l’un des bénéfices suivants :\n
      \n
    • Boost Your Data Science Career
    • \n
    • Stand Out From the Crowd
    • \n
    • Tackle Complex Questions
    • \n
    \n
  • \n
  • Description : chaque groupe d’annonces aura les trois variantes ci-dessous en rotation.\n
      \n
    • Learn Directly From the Top Experts in the Field. 20% off Annual Subscriptions
    • \n
    • Get Ahead of the Curve, Master Data Science Skills. $29 / Month. Cancel Anytime
    • \n
    • Choose From a Wide Variety of Topics Tuaght by the Best in the World. Start Now
    • \n
    \n
  • \n
\n

Créer les colonnes Campaign

\n
full_keywords_df.Campaign.unique()  # just to make sure you have consistent naming conventions\n
\n
array(['SEM_Instructors', 'SEM_Technologies', 'SEM_Courses', 'SEM_Tracks'], dtype=object)\n
\n
course_df['Campaign'] = 'SEM_Courses'\ncourse_df = course_df.rename(columns={'name_clean': 'name', 'name': 'old_name'})\ncourse_df.head()\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n
instructor_df['Campaign'] = 'SEM_Instructors'\ninstructor_df.head()\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n
tracks_df['Campaign'] = 'SEM_Tracks'\ntracks_df.head()\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n
tech_domain = 'https://www.datacamp.com/courses/tech:'\ntech_domain_list = []\nfor tech in ['R', 'Python', 'SQL', 'Git', 'Shell']:\n    tech_domain_list.append((tech, tech_domain + tech))\ntech_df = pd.DataFrame.from_records(tech_domain_list, columns=['name', 'url'])\ntech_df['Campaign'] = 'SEM_Technologies'\ntech_df\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 nameurlCampaign
0Rhttps://www.datacamp.com/category/rSEM_Technologies
1Pythonhttps://www.datacamp.com/category/pythonSEM_Technologies
2SQLhttps://www.datacamp.com/category/sqlSEM_Technologies
3Githttps://www.datacamp.com/courses/tech:GitSEM_Technologies
4Shellhttps://www.datacamp.com/category/shellSEM_Technologies
\n
\n

Fusionner tous les DataFrames ('name', 'url')

\n
full_ads_df = pd.concat([course_df[['Campaign', 'name', 'url']],\n                        instructor_df,\n                        tracks_df,\n                        tech_df], ignore_index=True)\nfull_ads_df = full_ads_df.rename(columns={'name': 'Ad Group', 'url': 'Final URL'})\nprint('total rows:', full_ads_df.shape[0])\nn_adgroups = full_ads_df.shape[0]\nfull_ads_df.head()\n
\n
total rows: 201\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n

Générer les annonces

\n

Pour faire le point : votre DataFrame des annonces contient désormais les colonnes Campaign, Ad Group et Final URL correctement mappées. Il vous reste à ajouter Headline 1, Headline 2 et Description.

\n

N’oubliez pas que vous allez créer trois variantes d’annonce par groupe d’annonces. C’est une bonne pratique pour tester : taux de clics, conversions, etc. Votre DataFrame final aura donc trois fois plus de lignes.

\n

Commencez par dupliquer chaque ligne trois fois dans full_ads_df :

\n
full_ads_df = full_ads_df.iloc[[x  for x in range(n_adgroups) for i in range(3)], :] \nprint('total rows:', full_ads_df.shape[0])\nfull_ads_df.head(9)\n
\n
total rows: 603\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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...
\n
\n


Ajoutez maintenant les trois descriptions créées ci-dessus.

\n
Description = [\n    'Learn Directly From the Top Experts in the Field. 20% off Annual Subcriptions',\n    'Be Ahead of the Curve, Master Data Science Skills. $29 / Month. Cancel Anytime',\n    'Choose From a Wide Variety of Topics Tuaght by the Best in the World. Start Now'   \n]\nDescription = [x for i in range(n_adgroups) for x in Description ]\nfull_ads_df['Description'] = Description\nfull_ads_df.head()\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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...
\n
\n


Ajoutez ensuite Headline 1 et Headline 2 au DataFrame. Vous y êtes presque !

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

Les bénéfices seront utilisés en Headline 2 lorsque la longueur du nom du groupe d’annonces est inférieure ou égale à 30 caractères. Dans ce cas, le second champ serait vide : vous le remplirez alors avec l’un des bénéfices.

\n
benefits = [x for i in range(n_adgroups) for x in benefits]\nheadlines = [split_string(x) for x in full_ads_df['Ad Group']]\nfull_ads_df['Headline 1'] = [x[0] for x in headlines]\nfull_ads_df['Headline 2'] = [x[1] if x[1] else benefits[i] for i, x in enumerate(headlines)]\nprint('total ads:', full_ads_df.shape[0])\nfull_ads_df.head(9)\n
\n
total ads: 603\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
 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
\n
\n


Comme vous le voyez, \"Intro to Python for Data Science\" est suffisamment long pour être scindé en deux champs : on le conserve tel quel pour plus de clarté. Dans le second cas, \"Introduction to R\" tient dans le premier titre, donc nous insérons tour à tour les trois bénéfices en Headline 2.

\n

Et c’est terminé !

\n

Vérifier une dernière fois

\n

Un contrôle rapide pour s’assurer que les noms de campagnes et de groupes d’annonces correspondent bien dans les deux DataFrames.

\n
ads_check = (full_ads_df[['Campaign', 'Ad Group']]\n             .drop_duplicates()\n             .sort_values(['Campaign', 'Ad Group'])\n             .reset_index(drop=True))\nkeywords_check = (full_keywords_df[['Campaign', 'Ad Group']]\n                  .drop_duplicates()\n                  .sort_values(['Campaign', 'Ad Group'])\n                  .reset_index(drop=True))\n\nall(ads_check == keywords_check)\n
\n
True\n
\n
full_ads_df.to_csv('ads.csv', index=False)\n
\n

Importer et lancer

\n

Comme indiqué, ce tutoriel couvre des étapes spécifiques d’une campagne SEM et suppose une compréhension de base du search marketing. Pour en savoir plus sur les modalités d’import et de lancement, consultez le guide AdWords pour bien démarrer. Pour accéder aux cours complets par thématique, consultez la Google Academy for Ads.

\n

Data science et SEM : encore beaucoup à explorer !

\n

Avec les deux fichiers CSV, vous pouvez les importer et lancer vos campagnes. Il vous restera à définir des budgets quotidiens, le ciblage géographique et quelques autres paramètres, mais l’essentiel est prêt.

\n

Pour consulter les fichiers CSV, rendez-vous ici :

\n\n

J’espère que ce tutoriel vous a été utile. Merci de votre lecture. Si vous souhaitez partager vos projets de croissance réalisés avec Python, contactez-moi sur Twitter @eliasdabbas.

Sujets
Science des données
Python

En savoir plus sur Python

Cours

Introduction à Python

4 h
7M
Apprenez les bases de l’analyse de données avec Python en quatre heures et explorez ses principaux packages.
Afficher les détailsRight Arrow
Commencer Le Cours
Voir plusRight Arrow