Comment importer des données brutes de Google Ads vers Google BigQuery

Publié: 2022-04-12

En analysant l'efficacité des campagnes publicitaires Google Ads dans Google Analytics, vous pouvez rencontrer des restrictions d'échantillonnage, d'agrégation de données ou d'autres interfaces système. Heureusement, ce problème est facilement résolu en téléchargeant les données brutes de votre service publicitaire vers Google BigQuery.

Dans cet article, vous apprendrez à importer des données brutes de votre compte Google Ads dans BigQuery et à identifier toutes les balises UTM pour les campagnes avec étiquetage automatique.

Vous avez besoin d'OWOX BI pour lier les informations de la campagne à l'activité des utilisateurs sur le site. Inscrivez-vous pour une démo et nous détaillerons tous les défis que vous pouvez résoudre avec OWOX BI.

INSCRIVEZ-VOUS POUR UNE DÉMO

Table des matières

  • Pourquoi vous avez besoin des données brutes de Google Ads
  • Deux façons d'importer des données brutes de Google Ads dans BigQuery
  • Comment configurer le téléchargement à l'aide du transfert de données
  • Comment configurer l'importation à l'aide d'Ads Script
  • Comment connecter le téléchargement de données de Google Ads à OWOX BI
  • Conseils utiles

Découvrez la valeur réelle des campagnes

Importez automatiquement les données de coût dans Google Analytics à partir de tous vos services publicitaires. Comparez les coûts de campagne, le CPC et le ROAS dans un seul rapport.

Commencer procès

Pourquoi vous avez besoin des données brutes de Google Ads

Les données brutes de Google Ads vous permettront d'analyser les campagnes publicitaires avec précision jusqu'à chaque mot-clé. En important des données dans BigQuery, vous pouvez :

  • Créez des rapports aussi détaillés que vous le souhaitez sans être limité par les restrictions GA.
  • Déterminez l'efficacité des campagnes publicitaires au niveau de la session et de l'utilisateur.
  • Calculez le retour sur investissement, le ROAS, le CRR par région, type d'utilisateur (nouveau ou de retour), appareil et tout autre paramètre.
  • Gérez efficacement vos tarifs et créez des listes de remarketing.
  • Combinez les données de Google Ads, Google Analytics et CRM pour évaluer l'efficacité des campagnes en fonction de la marge et de la possibilité de remboursement de vos articles.
  • Entraînez votre modèle ML pour une planification plus précise.

Pour comprendre quelles campagnes, annonces et mots clés amènent les utilisateurs sur votre site, vous devez combiner les données de Google Ads et Analytics dans BigQuery. Vous pouvez le faire en utilisant le streaming OWOX BI.

La diffusion en continu de ces informations envoie des données non échantillonnées sur le comportement des utilisateurs sur votre site à GBQ. Les hits sont transmis en temps réel, puis des sessions sont formées sur la base de ces hits.

ESSAYEZ OWOX BI GRATUITEMENT

Les informations sur la source de trafic OWOX BI sont extraites du balisage publicitaire des balises UTM. Les balises sont manuelles et automatiques.

Imaginons que vous ayez marqué l'annonce manuellement et que vous ayez cette URL :

https://example.com/?utm_source=facebook&utm_medium=cpc&utm_campaign=utm_tags

Dans ce cas, après avoir connecté OWOX BI, vous aurez des données de source, de canal et de campagne disponibles dans la table GBQ :

  • traficSource.source — google
  • trafficSource.medium — CPC
  • trafficSource.campaign — utm_tags

En savoir plus sur la création correcte de balises UTM.

Si vous avez activé le balisage automatique dans le service de publicité, un paramètre gclid spécial est attribué à chacune de vos annonces. Il est ajouté à l'URL de la page de destination lorsque l'utilisateur clique sur l'annonce.

Exemple d'un tel lien :

http://www.example.com/?gclid=TeSter-123

Si vous utilisez un balisage automatique, vous ne pouvez pas obtenir la source, le support ou la campagne de gclid sans données brutes. Ces champs seront vides dans les tables BigQuery collectées par OWOX BI.

Que pouvez-vous faire dans un tel cas et comment pouvez-vous obtenir le nom des campagnes et d'autres paramètres, n'ayant que le gclid ? Configurez le téléchargement automatique de Google Ads vers GBQ.

Remarque : si l'annonce n'est pas marquée du tout, OWOX BI attribuera le lien comme suit :

  • pour les sources autres que Google en tant que trafic de référence (par exemple, facebook/référence)
  • pour la source Google en tant que trafic direct (direct/aucun)

S'il y a beaucoup de trafic direct/aucun dans vos rapports, il se peut que vous n'ayez pas activé le filtrage des bots ou que vous ayez un grand nombre d'annonces non taguées.

Deux façons d'importer des données brutes de Google Ads dans BigQuery

Nous utilisons et recommandons deux méthodes pour importer des données brutes depuis Google Ads : le connecteur de transfert de données et le script publicitaire.

La méthode que vous choisissez dépend de vos objectifs et de votre budget.

Fonctionnalités de transfert de données

  • Intégration native avec GBQ.
  • Téléchargez des données historiques pour n'importe quelle période sans restrictions.
  • Gratuit.

Fonctionnalités Google AdsScript

  • Libre.
  • Vous ne pouvez pas télécharger de données historiques. Seules les informations de la veille sont téléchargées.
  • Nécessite plus si vous souhaitez configurer le téléchargement à partir d'un grand nombre de comptes. Vous devrez apporter manuellement des modifications au script pour chaque compte. Dans le même temps, le risque de se tromper est élevé.

Ce dont vous avez besoin pour les paramètres

Projets et comptes actifs dans :

  • Plate-forme Google Cloud (GCP)
  • Google BigQuery (GBQ)
  • OWOX BI
  • Annonces Google

Accéder:

  • Propriétaire dans GCP
  • Administrateur chez GBQ
  • Édition dans OWOX BI. Important : seul l'utilisateur qui a créé le pipeline de streaming Google Analytics → Google BigQuery peut activer le téléchargement depuis Google Ads.
  • Lire dans Google Ads

Comment accorder des droits d'accès dans GBQ

Ouvrez la console GCP et sélectionnez IAM et admin — Gérer les ressources dans le menu latéral. Sélectionnez ensuite le projet et cliquez sur Ajouter un membre. Saisissez l'adresse e-mail de l'utilisateur, sélectionnez le rôle d'administrateur BigQuery et enregistrez vos modifications.

Accès BigQuery

Comment configurer le téléchargement à l'aide du transfert de données

Étape 1. Créer un projet dans Google Cloud Platform

Si vous avez déjà un projet dans GCP, ignorez cette étape. Si ce n'est pas le cas, ouvrez la console GCP et sélectionnez IAM et admin — Gérer les ressources dans le menu latéral. Cliquez sur le bouton Créer un projet. Saisissez ensuite le nom du projet, spécifiez l'organisation, puis cliquez sur Créer :

Google Cloud Platform – Configuration d'un projet

Assurez-vous d'activer la facturation. Pour ce faire, ouvrez l'onglet Facturation — Gestion du compte dans le menu latéral, sélectionnez le projet et liez Compte de facturation :

Facturation dans Google Cloud Platform

Ensuite, remplissez tous les champs en entrant vos contacts et les détails de votre carte de paiement. S'il s'agit de votre premier projet dans GCP, vous recevrez 300 $ utilisables pendant 12 mois. Les projets qui ont 1 à 2 comptes Google Ads et jusqu'à 100 000 utilisateurs uniques par mois en auront assez pour un an. Lorsque vous épuisez cette limite, vous n'avez pas besoin de restituer l'argent. Pour une utilisation ultérieure, il vous suffit de recharger le solde de la carte que vous avez liée au projet.

Étape 2. Activez l'API BigQuery

Après avoir créé un projet, vous devez activer l'API BigQuery. Pour ce faire, accédez à API et services – Tableau de bord dans le menu latéral de GCP, sélectionnez le projet, puis cliquez sur Activer les API et les services :

Activation de l'API BigQuery

Dans la bibliothèque d'API, recherchez "API BigQuery", puis cliquez sur Activer :

activer l'API BigQuery

Pour utiliser l'API, cliquez sur Créer des identifiants :

Créer des identifiants

Dans la liste déroulante, choisissez l'API BigQuery et cliquez sur De quelles informations d'identification ai-je besoin ?

Choix des identifiants

Créez le nom du compte de service et spécifiez le niveau d'accès du rôle BigQuery. Sélectionnez le type de clé JSON et cliquez sur Continuer :

Spécifiez les informations d'identification

Étape 3. Activer l'API de transfert de données

Ensuite, vous devez activer le service de données dans BigQuery. Pour ce faire, ouvrez GBQ et sélectionnez Transferts dans le menu latéral à gauche. Activez ensuite l'API BigQuery Data Transfer :

activer l'API de transfert de données BigQuery

Étape 4. Préparer l'ensemble de données dans GBQ

Dans BigQuery, sélectionnez le projet et cliquez sur le bouton Créer un ensemble de données à droite. Remplissez tous les champs obligatoires pour le nouveau jeu de données (nom, emplacement, rétention) :

créer le jeu de données dans GBQ

Étape 5. Configurer le transfert de données depuis Google Ads

Cliquez sur l'onglet Transferts dans le menu latéral, puis cliquez sur Créer un transfert. Sélectionnez ensuite Google Ads (anciennement AdWords) comme source et saisissez le nom du téléchargement, par exemple, Transfert de données.

Sous Options de planification, vous pouvez laisser la valeur par défaut sur Démarrer maintenant ou définir la date et l'heure auxquelles vous souhaitez commencer le téléchargement. Dans le champ Répétitions, sélectionnez la fréquence de téléchargement : quotidienne, hebdomadaire, mensuelle à la demande, etc.

Paramètres de transfert de données

Ensuite, vous devez spécifier l'ensemble de données GBQ dans lequel charger les rapports de Google Ads. Saisissez l'identifiant client (il s'agit de l'identifiant de votre compte Google Ads ou de l'identifiant CM) et cliquez sur Ajouter. Vous pouvez afficher le numéro client dans votre compte Google Ads dans l'angle supérieur droit, à côté de votre adresse e-mail.

Spécifier les paramètres de transfert de données

Ensuite, vous devez autoriser le compte Gmail que vous utilisez. Le jour suivant, les informations apparaîtront dans l'ensemble de données que vous avez spécifié lors de la configuration du transfert.

En conséquence, vous recevrez une grande quantité de données brutes dans GBQ avec lesquelles vous pourrez travailler : des tableaux par campagnes, des audiences, des tableaux communs (personnalisés), des mots-clés et des conversions. Par exemple, si vous souhaitez créer un tableau de bord personnalisé, vous pouvez extraire des données non agrégées de ces tables.

Comment configurer l'importation à l'aide d'Ads Script

Ouvrez votre compte Google Ads, cliquez sur Outils et paramètres dans l'angle supérieur droit, sélectionnez Actions groupées — Scripts, puis cliquez sur le symbole Plus :

Script dans Google Ads

Ensuite, dans l'angle supérieur droit, cliquez sur le bouton API avancées, sélectionnez BigQuery et enregistrez vos modifications :

Enregistrement des modifications

Assurez-vous de vous inscrire avec le compte avec lequel vous vous êtes connecté à Google Ads :

Autorisation Google Ads

Copiez le script ci-dessous. Dans les lignes BIGQUERY_PROJECT_ID, BIGQUERY_DATASET_ID et Votre e-mail, remplacez les valeurs par vos propres informations : nom du projet, ensemble de données GBQ et e-mail. Collez le texte du script dans l'éditeur de texte.

    /** * @name Export Data to BigQuery * * @overview The Export Data to BigQuery script sets up a BigQuery * dataset and tables, downloads a report from AdWords and then * loads the report to BigQuery. * * @author AdWords Scripts Team [[email protected]] * * @version 1.3 */ var CONFIG = { BIGQUERY_PROJECT_ID: 'BQ project name', BIGQUERY_DATASET_ID: AdWordsApp.currentAccount().getCustomerId().replace(/-/g, '_'), // Truncate existing data, otherwise will append. TRUNCATE_EXISTING_DATASET: false, TRUNCATE_EXISTING_TABLES: true, // Lists of reports and fields to retrieve from AdWords. REPORTS: [], RECIPIENT_EMAILS: [ 'Your email' ] }; var report = { NAME: 'CLICK_PERFORMANCE_REPORT', //https://developers.google.com/adwords/api/docs/appendix/reports/click-performance-report CONDITIONS: '', FIELDS: {'AccountDescriptiveName': 'STRING', 'AdFormat': 'STRING', 'AdGroupId': 'STRING', 'AdGroupName': 'STRING', 'AoiCountryCriteriaId': 'STRING', 'CampaignId': 'STRING', 'CampaignLocationTargetId': 'STRING', 'CampaignName': 'STRING', 'CampaignStatus': 'STRING', 'Clicks': 'INTEGER', 'ClickType': 'STRING', 'CreativeId': 'STRING', 'CriteriaId': 'STRING', 'CriteriaParameters': 'STRING', 'Date': 'DATE', 'Device': 'STRING', 'ExternalCustomerId': 'STRING', 'GclId': 'STRING', 'KeywordMatchType': 'STRING', 'LopCountryCriteriaId': 'STRING', 'Page': 'INTEGER' }, DATE_RANGE: new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, "")+','+new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, ""), DATE: new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, "") }; //Regular export CONFIG.REPORTS.push(JSON.parse(JSON.stringify(report))); //One-time historical export //for(var i=2;i<91;i++){ // report.DATE_RANGE = new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, "")+','+new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, ""); // report.DATE = new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, ""); // CONFIG.REPORTS.push(JSON.parse(JSON.stringify(report))); //} /** * Main method */ function main() { createDataset(); for (var i = 0; i < CONFIG.REPORTS.length; i++) { var reportConfig = CONFIG.REPORTS[i]; createTable(reportConfig); } var jobIds = processReports(); waitTillJobsComplete(jobIds); sendEmail(jobIds); } /** * Creates a new dataset. * * If a dataset with the same id already exists and the truncate flag * is set, will truncate the old dataset. If the truncate flag is not * set, then will not create a new dataset. */ function createDataset() { if (datasetExists()) { if (CONFIG.TRUNCATE_EXISTING_DATASET) { BigQuery.Datasets.remove(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID, {'deleteContents' : true}); Logger.log('Truncated dataset.'); } else { Logger.log('Dataset %s already exists. Will not recreate.', CONFIG.BIGQUERY_DATASET_ID); return; } } // Create new dataset. var dataSet = BigQuery.newDataset(); dataSet.friendlyName = CONFIG.BIGQUERY_DATASET_ID; dataSet.datasetReference = BigQuery.newDatasetReference(); dataSet.datasetReference.projectId = CONFIG.BIGQUERY_PROJECT_ID; dataSet.datasetReference.datasetId = CONFIG.BIGQUERY_DATASET_ID; dataSet = BigQuery.Datasets.insert(dataSet, CONFIG.BIGQUERY_PROJECT_ID); Logger.log('Created dataset with id %s.', dataSet.id); } /** * Checks if dataset already exists in project. * * @return {boolean} Returns true if dataset already exists. */ function datasetExists() { // Get a list of all datasets in project. var datasets = BigQuery.Datasets.list(CONFIG.BIGQUERY_PROJECT_ID); var datasetExists = false; // Iterate through each dataset and check for an id match. if (datasets.datasets != null) { for (var i = 0; i < datasets.datasets.length; i++) { var dataset = datasets.datasets[i]; if (dataset.datasetReference.datasetId == CONFIG.BIGQUERY_DATASET_ID) { datasetExists = true; break; } } } return datasetExists; } /** * Creates a new table. * * If a table with the same id already exists and the truncate flag * is set, will truncate the old table. If the truncate flag is not * set, then will not create a new table. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. */ function createTable(reportConfig) { var tableName = reportConfig.NAME+reportConfig.DATE; if (tableExists(tableName)) { if (CONFIG.TRUNCATE_EXISTING_TABLES) { BigQuery.Tables.remove(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID, tableName); Logger.log('Truncated table %s.', tableName); } else { Logger.log('Table %s already exists. Will not recreate.', tableName); return; } } // Create new table. var table = BigQuery.newTable(); var schema = BigQuery.newTableSchema(); var bigQueryFields = []; // Add each field to table schema. var fieldNames = Object.keys(reportConfig.FIELDS); for (var i = 0; i < fieldNames.length; i++) { var fieldName = fieldNames[i]; var bigQueryFieldSchema = BigQuery.newTableFieldSchema(); bigQueryFieldSchema.description = fieldName; bigQueryFieldSchema.name = fieldName; bigQueryFieldSchema.type = reportConfig.FIELDS[fieldName]; bigQueryFields.push(bigQueryFieldSchema); } schema.fields = bigQueryFields; table.schema = schema; table.friendlyName = tableName; table.tableReference = BigQuery.newTableReference(); table.tableReference.datasetId = CONFIG.BIGQUERY_DATASET_ID; table.tableReference.projectId = CONFIG.BIGQUERY_PROJECT_ID; table.tableReference.tableId = tableName; table = BigQuery.Tables.insert(table, CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID); Logger.log('Created table with id %s.', table.id); } /** * Checks if table already exists in dataset. * * @param {string} tableId The table id to check existence. * * @return {boolean} Returns true if table already exists. */ function tableExists(tableId) { // Get a list of all tables in the dataset. var tables = BigQuery.Tables.list(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID); var tableExists = false; // Iterate through each table and check for an id match. if (tables.tables != null) { for (var i = 0; i < tables.tables.length; i++) { var table = tables.tables[i]; if (table.tableReference.tableId == tableId) { tableExists = true; break; } } } return tableExists; } /** * Process all configured reports * * Iterates through each report to: retrieve AdWords data, * backup data to Drive (if configured), load data to BigQuery. * * @return {Array.<string>} jobIds The list of all job ids. */ function processReports() { var jobIds = []; // Iterate over each report type. for (var i = 0; i < CONFIG.REPORTS.length; i++) { var reportConfig = CONFIG.REPORTS[i]; Logger.log('Running report %s', reportConfig.NAME); // Get data as csv var csvData = retrieveAdwordsReport(reportConfig); //Logger.log(csvData); // Convert to Blob format. var blobData = Utilities.newBlob(csvData, 'application/octet-stream'); // Load data var jobId = loadDataToBigquery(reportConfig, blobData); jobIds.push(jobId); } return jobIds; } /** * Retrieves AdWords data as csv and formats any fields * to BigQuery expected format. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. * * @return {string} csvData Report in csv format. */ function retrieveAdwordsReport(reportConfig) { var fieldNames = Object.keys(reportConfig.FIELDS); var query = 'SELECT ' + fieldNames.join(', ') + ' FROM ' + reportConfig.NAME + '' + reportConfig.CONDITIONS + ' DURING ' + reportConfig.DATE_RANGE; Logger.log(query); var report = AdWordsApp.report(query); var rows = report.rows(); var csvRows = []; // Header row csvRows.push(fieldNames.join(',')); // Iterate over each row. while (rows.hasNext()) { var row = rows.next(); var csvRow = []; for (var i = 0; i < fieldNames.length; i++) { var fieldName = fieldNames[i]; var fieldValue = row[fieldName].toString(); var fieldType = reportConfig.FIELDS[fieldName]; // Strip off % and perform any other formatting here. if (fieldType == 'FLOAT' || fieldType == 'INTEGER') { if (fieldValue.charAt(fieldValue.length - 1) == '%') { fieldValue = fieldValue.substring(0, fieldValue.length - 1); } fieldValue = fieldValue.replace(/,/g,''); if (fieldValue == '--' || fieldValue == 'Unspecified') { fieldValue = '' } } // Add double quotes to any string values. if (fieldType == 'STRING') { if (fieldValue == '--') { fieldValue = '' } fieldValue = fieldValue.replace(/"/g, '""'); fieldValue = '"' + fieldValue + '"' } csvRow.push(fieldValue); } csvRows.push(csvRow.join(',')); } Logger.log('Downloaded ' + reportConfig.NAME + ' with ' + csvRows.length + ' rows.'); return csvRows.join('\n'); } /** * Creates a BigQuery insertJob to load csv data. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. * @param {Blob} data Csv report data as an 'application/octet-stream' blob. * * @return {string} jobId The job id for upload. */ function loadDataToBigquery(reportConfig, data) { // Create the data upload job. var job = { configuration: { load: { destinationTable: { projectId: CONFIG.BIGQUERY_PROJECT_ID, datasetId: CONFIG.BIGQUERY_DATASET_ID, tableId: reportConfig.NAME + reportConfig.DATE }, skipLeadingRows: 1 } } }; var insertJob = BigQuery.Jobs.insert(job, CONFIG.BIGQUERY_PROJECT_ID, data); Logger.log('Load job started for %s. Check on the status of it here: ' + 'https://bigquery.cloud.google.com/jobs/%s', reportConfig.NAME, CONFIG.BIGQUERY_PROJECT_ID); return insertJob.jobReference.jobId; } /** * Polls until all jobs are 'DONE'. * * @param {Array.<string>} jobIds The list of all job ids. */ function waitTillJobsComplete(jobIds) { var complete = false; var remainingJobs = jobIds; while (!complete) { if (AdWordsApp.getExecutionInfo().getRemainingTime() < 5){ Logger.log('Script is about to timeout, jobs ' + remainingJobs.join(',') + ' are still incomplete.'); } remainingJobs = getIncompleteJobs(remainingJobs); if (remainingJobs.length == 0) { complete = true; } if (!complete) { Logger.log(remainingJobs.length + ' jobs still being processed.'); // Wait 5 seconds before checking status again. Utilities.sleep(5000); } } Logger.log('All jobs processed.'); } /** * Iterates through jobs and returns the ids for those jobs * that are not 'DONE'. * * @param {Array.<string>} jobIds The list of job ids. * * @return {Array.<string>} remainingJobIds The list of remaining job ids. */ function getIncompleteJobs(jobIds) { var remainingJobIds = []; for (var i = 0; i < jobIds.length; i++) { var jobId = jobIds[i]; var getJob = BigQuery.Jobs.get(CONFIG.BIGQUERY_PROJECT_ID, jobId); if (getJob.status.state != 'DONE') { remainingJobIds.push(jobId); } } return remainingJobIds; } /** * Sends a notification email that jobs have completed loading. * * @param {Array.<string>} jobIds The list of all job ids. */ function sendEmail(jobIds) { var html = []; html.push( '<html>', '<body>', '<table width=800 cellpadding=0 border=0 cellspacing=0>', '<tr>', '<td colspan=2 align=right>', "<div style='font: italic normal 10pt Times New Roman, serif; " + "margin: 0; color: #666; padding-right: 5px;'>" + 'Powered by AdWords Scripts</div>', '</td>', '</tr>', "<tr bgcolor='#3c78d8'>", '<td width=500>', "<div style='font: normal 18pt verdana, sans-serif; " + "padding: 3px 10px; color: white'>Adwords data load to " + "Bigquery report</div>", '</td>', '<td align=right>', "<div style='font: normal 18pt verdana, sans-serif; " + "padding: 3px 10px; color: white'>", AdWordsApp.currentAccount().getCustomerId(), '</tr>', '</table>', '<table width=800 cellpadding=0 border=1 cellspacing=0>', "<tr bgcolor='#ddd'>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5px 5px; background-color: #ddd; ' + "text-align: left'>Report</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5px 5px; background-color: #ddd; ' + "text-align: left'>JobId</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>Rows</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>State</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>ErrorResult</td>", '</tr>', createTableRows(jobIds), '</table>', '</body>', '</html>'); MailApp.sendEmail(CONFIG.RECIPIENT_EMAILS.join(','), 'Adwords data load to Bigquery Complete', '', {htmlBody: html.join('\n')}); } /** * Creates table rows for email report. * * @param {Array.<string>} jobIds The list of all job ids. */ function createTableRows(jobIds) { var html = []; for (var i = 0; i < jobIds.length; i++) { var jobId = jobIds[i]; var job = BigQuery.Jobs.get(CONFIG.BIGQUERY_PROJECT_ID, jobId); var errorResult = '' if (job.status.errorResult) { errorResult = job.status.errorResult; } html.push('<tr>', "<td style='padding: 0px 10px'>" + job.configuration.load.destinationTable.tableId + '</td>', "<td style='padding: 0px 10px'>" + jobId + '</td>', "<td style='padding: 0px 10px'>" + job.statistics.load?job.statistics.load.outputRows:0 + '</td>', "<td style='padding: 0px 10px'>" + job.status.state + '</td>', "<td style='padding: 0px 10px'>" + errorResult + '</td>', '</tr>'); } return html.join('\n'); }
/** * @name Export Data to BigQuery * * @overview The Export Data to BigQuery script sets up a BigQuery * dataset and tables, downloads a report from AdWords and then * loads the report to BigQuery. * * @author AdWords Scripts Team [[email protected]] * * @version 1.3 */ var CONFIG = { BIGQUERY_PROJECT_ID: 'BQ project name', BIGQUERY_DATASET_ID: AdWordsApp.currentAccount().getCustomerId().replace(/-/g, '_'), // Truncate existing data, otherwise will append. TRUNCATE_EXISTING_DATASET: false, TRUNCATE_EXISTING_TABLES: true, // Lists of reports and fields to retrieve from AdWords. REPORTS: [], RECIPIENT_EMAILS: [ 'Your email' ] }; var report = { NAME: 'CLICK_PERFORMANCE_REPORT', //https://developers.google.com/adwords/api/docs/appendix/reports/click-performance-report CONDITIONS: '', FIELDS: {'AccountDescriptiveName': 'STRING', 'AdFormat': 'STRING', 'AdGroupId': 'STRING', 'AdGroupName': 'STRING', 'AoiCountryCriteriaId': 'STRING', 'CampaignId': 'STRING', 'CampaignLocationTargetId': 'STRING', 'CampaignName': 'STRING', 'CampaignStatus': 'STRING', 'Clicks': 'INTEGER', 'ClickType': 'STRING', 'CreativeId': 'STRING', 'CriteriaId': 'STRING', 'CriteriaParameters': 'STRING', 'Date': 'DATE', 'Device': 'STRING', 'ExternalCustomerId': 'STRING', 'GclId': 'STRING', 'KeywordMatchType': 'STRING', 'LopCountryCriteriaId': 'STRING', 'Page': 'INTEGER' }, DATE_RANGE: new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, "")+','+new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, ""), DATE: new Date(new Date().setDate(new Date().getDate()-1)).toISOString().slice(0, 10).replace(/-/g, "") }; //Regular export CONFIG.REPORTS.push(JSON.parse(JSON.stringify(report))); //One-time historical export //for(var i=2;i<91;i++){ // report.DATE_RANGE = new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, "")+','+new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, ""); // report.DATE = new Date(new Date().setDate(new Date().getDate()-i)).toISOString().slice(0, 10).replace(/-/g, ""); // CONFIG.REPORTS.push(JSON.parse(JSON.stringify(report))); //} /** * Main method */ function main() { createDataset(); for (var i = 0; i < CONFIG.REPORTS.length; i++) { var reportConfig = CONFIG.REPORTS[i]; createTable(reportConfig); } var jobIds = processReports(); waitTillJobsComplete(jobIds); sendEmail(jobIds); } /** * Creates a new dataset. * * If a dataset with the same id already exists and the truncate flag * is set, will truncate the old dataset. If the truncate flag is not * set, then will not create a new dataset. */ function createDataset() { if (datasetExists()) { if (CONFIG.TRUNCATE_EXISTING_DATASET) { BigQuery.Datasets.remove(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID, {'deleteContents' : true}); Logger.log('Truncated dataset.'); } else { Logger.log('Dataset %s already exists. Will not recreate.', CONFIG.BIGQUERY_DATASET_ID); return; } } // Create new dataset. var dataSet = BigQuery.newDataset(); dataSet.friendlyName = CONFIG.BIGQUERY_DATASET_ID; dataSet.datasetReference = BigQuery.newDatasetReference(); dataSet.datasetReference.projectId = CONFIG.BIGQUERY_PROJECT_ID; dataSet.datasetReference.datasetId = CONFIG.BIGQUERY_DATASET_ID; dataSet = BigQuery.Datasets.insert(dataSet, CONFIG.BIGQUERY_PROJECT_ID); Logger.log('Created dataset with id %s.', dataSet.id); } /** * Checks if dataset already exists in project. * * @return {boolean} Returns true if dataset already exists. */ function datasetExists() { // Get a list of all datasets in project. var datasets = BigQuery.Datasets.list(CONFIG.BIGQUERY_PROJECT_ID); var datasetExists = false; // Iterate through each dataset and check for an id match. if (datasets.datasets != null) { for (var i = 0; i < datasets.datasets.length; i++) { var dataset = datasets.datasets[i]; if (dataset.datasetReference.datasetId == CONFIG.BIGQUERY_DATASET_ID) { datasetExists = true; break; } } } return datasetExists; } /** * Creates a new table. * * If a table with the same id already exists and the truncate flag * is set, will truncate the old table. If the truncate flag is not * set, then will not create a new table. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. */ function createTable(reportConfig) { var tableName = reportConfig.NAME+reportConfig.DATE; if (tableExists(tableName)) { if (CONFIG.TRUNCATE_EXISTING_TABLES) { BigQuery.Tables.remove(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID, tableName); Logger.log('Truncated table %s.', tableName); } else { Logger.log('Table %s already exists. Will not recreate.', tableName); return; } } // Create new table. var table = BigQuery.newTable(); var schema = BigQuery.newTableSchema(); var bigQueryFields = []; // Add each field to table schema. var fieldNames = Object.keys(reportConfig.FIELDS); for (var i = 0; i < fieldNames.length; i++) { var fieldName = fieldNames[i]; var bigQueryFieldSchema = BigQuery.newTableFieldSchema(); bigQueryFieldSchema.description = fieldName; bigQueryFieldSchema.name = fieldName; bigQueryFieldSchema.type = reportConfig.FIELDS[fieldName]; bigQueryFields.push(bigQueryFieldSchema); } schema.fields = bigQueryFields; table.schema = schema; table.friendlyName = tableName; table.tableReference = BigQuery.newTableReference(); table.tableReference.datasetId = CONFIG.BIGQUERY_DATASET_ID; table.tableReference.projectId = CONFIG.BIGQUERY_PROJECT_ID; table.tableReference.tableId = tableName; table = BigQuery.Tables.insert(table, CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID); Logger.log('Created table with id %s.', table.id); } /** * Checks if table already exists in dataset. * * @param {string} tableId The table id to check existence. * * @return {boolean} Returns true if table already exists. */ function tableExists(tableId) { // Get a list of all tables in the dataset. var tables = BigQuery.Tables.list(CONFIG.BIGQUERY_PROJECT_ID, CONFIG.BIGQUERY_DATASET_ID); var tableExists = false; // Iterate through each table and check for an id match. if (tables.tables != null) { for (var i = 0; i < tables.tables.length; i++) { var table = tables.tables[i]; if (table.tableReference.tableId == tableId) { tableExists = true; break; } } } return tableExists; } /** * Process all configured reports * * Iterates through each report to: retrieve AdWords data, * backup data to Drive (if configured), load data to BigQuery. * * @return {Array.<string>} jobIds The list of all job ids. */ function processReports() { var jobIds = []; // Iterate over each report type. for (var i = 0; i < CONFIG.REPORTS.length; i++) { var reportConfig = CONFIG.REPORTS[i]; Logger.log('Running report %s', reportConfig.NAME); // Get data as csv var csvData = retrieveAdwordsReport(reportConfig); //Logger.log(csvData); // Convert to Blob format. var blobData = Utilities.newBlob(csvData, 'application/octet-stream'); // Load data var jobId = loadDataToBigquery(reportConfig, blobData); jobIds.push(jobId); } return jobIds; } /** * Retrieves AdWords data as csv and formats any fields * to BigQuery expected format. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. * * @return {string} csvData Report in csv format. */ function retrieveAdwordsReport(reportConfig) { var fieldNames = Object.keys(reportConfig.FIELDS); var query = 'SELECT ' + fieldNames.join(', ') + ' FROM ' + reportConfig.NAME + '' + reportConfig.CONDITIONS + ' DURING ' + reportConfig.DATE_RANGE; Logger.log(query); var report = AdWordsApp.report(query); var rows = report.rows(); var csvRows = []; // Header row csvRows.push(fieldNames.join(',')); // Iterate over each row. while (rows.hasNext()) { var row = rows.next(); var csvRow = []; for (var i = 0; i < fieldNames.length; i++) { var fieldName = fieldNames[i]; var fieldValue = row[fieldName].toString(); var fieldType = reportConfig.FIELDS[fieldName]; // Strip off % and perform any other formatting here. if (fieldType == 'FLOAT' || fieldType == 'INTEGER') { if (fieldValue.charAt(fieldValue.length - 1) == '%') { fieldValue = fieldValue.substring(0, fieldValue.length - 1); } fieldValue = fieldValue.replace(/,/g,''); if (fieldValue == '--' || fieldValue == 'Unspecified') { fieldValue = '' } } // Add double quotes to any string values. if (fieldType == 'STRING') { if (fieldValue == '--') { fieldValue = '' } fieldValue = fieldValue.replace(/"/g, '""'); fieldValue = '"' + fieldValue + '"' } csvRow.push(fieldValue); } csvRows.push(csvRow.join(',')); } Logger.log('Downloaded ' + reportConfig.NAME + ' with ' + csvRows.length + ' rows.'); return csvRows.join('\n'); } /** * Creates a BigQuery insertJob to load csv data. * * @param {Object} reportConfig Report configuration including report name, * conditions, and fields. * @param {Blob} data Csv report data as an 'application/octet-stream' blob. * * @return {string} jobId The job id for upload. */ function loadDataToBigquery(reportConfig, data) { // Create the data upload job. var job = { configuration: { load: { destinationTable: { projectId: CONFIG.BIGQUERY_PROJECT_ID, datasetId: CONFIG.BIGQUERY_DATASET_ID, tableId: reportConfig.NAME + reportConfig.DATE }, skipLeadingRows: 1 } } }; var insertJob = BigQuery.Jobs.insert(job, CONFIG.BIGQUERY_PROJECT_ID, data); Logger.log('Load job started for %s. Check on the status of it here: ' + 'https://bigquery.cloud.google.com/jobs/%s', reportConfig.NAME, CONFIG.BIGQUERY_PROJECT_ID); return insertJob.jobReference.jobId; } /** * Polls until all jobs are 'DONE'. * * @param {Array.<string>} jobIds The list of all job ids. */ function waitTillJobsComplete(jobIds) { var complete = false; var remainingJobs = jobIds; while (!complete) { if (AdWordsApp.getExecutionInfo().getRemainingTime() < 5){ Logger.log('Script is about to timeout, jobs ' + remainingJobs.join(',') + ' are still incomplete.'); } remainingJobs = getIncompleteJobs(remainingJobs); if (remainingJobs.length == 0) { complete = true; } if (!complete) { Logger.log(remainingJobs.length + ' jobs still being processed.'); // Wait 5 seconds before checking status again. Utilities.sleep(5000); } } Logger.log('All jobs processed.'); } /** * Iterates through jobs and returns the ids for those jobs * that are not 'DONE'. * * @param {Array.<string>} jobIds The list of job ids. * * @return {Array.<string>} remainingJobIds The list of remaining job ids. */ function getIncompleteJobs(jobIds) { var remainingJobIds = []; for (var i = 0; i < jobIds.length; i++) { var jobId = jobIds[i]; var getJob = BigQuery.Jobs.get(CONFIG.BIGQUERY_PROJECT_ID, jobId); if (getJob.status.state != 'DONE') { remainingJobIds.push(jobId); } } return remainingJobIds; } /** * Sends a notification email that jobs have completed loading. * * @param {Array.<string>} jobIds The list of all job ids. */ function sendEmail(jobIds) { var html = []; html.push( '<html>', '<body>', '<table width=800 cellpadding=0 border=0 cellspacing=0>', '<tr>', '<td colspan=2 align=right>', "<div style='font: italic normal 10pt Times New Roman, serif; " + "margin: 0; color: #666; padding-right: 5px;'>" + 'Powered by AdWords Scripts</div>', '</td>', '</tr>', "<tr bgcolor='#3c78d8'>", '<td width=500>', "<div style='font: normal 18pt verdana, sans-serif; " + "padding: 3px 10px; color: white'>Adwords data load to " + "Bigquery report</div>", '</td>', '<td align=right>', "<div style='font: normal 18pt verdana, sans-serif; " + "padding: 3px 10px; color: white'>", AdWordsApp.currentAccount().getCustomerId(), '</tr>', '</table>', '<table width=800 cellpadding=0 border=1 cellspacing=0>', "<tr bgcolor='#ddd'>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5px 5px; background-color: #ddd; ' + "text-align: left'>Report</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5px 5px; background-color: #ddd; ' + "text-align: left'>JobId</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>Rows</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>State</td>", "<td style='font: 12pt verdana, sans-serif; " + 'padding: 5px 0px 5x 5px; background-color: #ddd; ' + "text-align: left'>ErrorResult</td>", '</tr>', createTableRows(jobIds), '</table>', '</body>', '</html>'); MailApp.sendEmail(CONFIG.RECIPIENT_EMAILS.join(','), 'Adwords data load to Bigquery Complete', '', {htmlBody: html.join('\n')}); } /** * Creates table rows for email report. * * @param {Array.<string>} jobIds The list of all job ids. */ function createTableRows(jobIds) { var html = []; for (var i = 0; i < jobIds.length; i++) { var jobId = jobIds[i]; var job = BigQuery.Jobs.get(CONFIG.BIGQUERY_PROJECT_ID, jobId); var errorResult = '' if (job.status.errorResult) { errorResult = job.status.errorResult; } html.push('<tr>', "<td style='padding: 0px 10px'>" + job.configuration.load.destinationTable.tableId + '</td>', "<td style='padding: 0px 10px'>" + jobId + '</td>', "<td style='padding: 0px 10px'>" + job.statistics.load?job.statistics.load.outputRows:0 + '</td>', "<td style='padding: 0px 10px'>" + job.status.state + '</td>', "<td style='padding: 0px 10px'>" + errorResult + '</td>', '</tr>'); } return html.join('\n'); }

Avant d'exécuter le script, assurez-vous de cliquer sur le bouton Aperçu dans le coin inférieur droit pour vérifier le résultat. S'il contient des erreurs, le système vous avertira et indiquera dans quelle ligne cela s'est produit, comme dans cette capture d'écran :

Exécutez le script

S'il n'y a pas d'erreurs, cliquez sur le bouton Exécuter :

configurer le téléchargement depuis Google Ads

En conséquence, vous recevrez un nouveau rapport CLICK_PERFORMANCE_REPORT dans votre GBQ qui sera disponible le lendemain :

résultats en GBQ

N'oubliez pas que lorsque vous utilisez le transfert de données, vous obtenez une grande quantité de données brutes non agrégées. Avec Ads Script, vous n'aurez des informations que sur certains champs.

Les champs suivants de ce téléchargement sont inclus dans les tables OWOX BI liées à la session :

  • GclId
  • ID de campagne
  • Nom de la campagne
  • ID du groupe d'annonces
  • Nom du groupe d'annonces
  • Identifiant des critères
  • CritèresParamètres
  • KeywordMatchType

Comment connecter le téléchargement de données de Google Ads à OWOX BI

Vous devez maintenant combiner les informations de Google Ads avec les données du site pour comprendre par quelles campagnes les utilisateurs ont accédé à votre site. Les tables que vous obtenez dans BigQuery, telles que Data Transfer, n'ont pas de paramètre d'ID client. Vous ne pouvez déterminer quel client a cliqué sur les publicités qu'en liant les données gclid aux données de flux OWOX BI.

Si vous n'avez pas encore de pipeline de streaming Google Analytics → Google BigQuery dans OWOX BI, lisez les instructions pour le créer.

Accédez ensuite à votre projet OWOX BI et ouvrez ce pipeline. Cliquez sur l'onglet Paramètres, puis sous Collecte de données de session, cliquez sur Modifier les paramètres :

Paramètres du pipeline OWOX BI

Utilisez le curseur pour activer la collecte de données pour les campagnes avec libellé automatique Google Ads et cliquez sur Modifier les paramètres :

activer la collecte de données pour Google Ads

Sélectionnez le type de balisage AutoLabel, indiquez comment charger les scripts de transfert de données ou d'annonces dans BigQuery. Spécifiez le projet et l'ensemble de données à partir desquels les données Google Ads seront téléchargées et enregistrez vos paramètres :

Enregistrer les paramètres

Conseils utiles

Astuce 1. Avec le transfert de données, vous pouvez télécharger des données historiques de Google Ads vers GBQ. Dans le même temps, il n'y a aucune restriction sur la période totale de chargement (soit pour un an, soit pour trois), mais avec des données pour seulement 180 jours à la fois.

Vous pouvez activer le téléchargement et spécifier la période à l'aide du bouton Planifier le remplissage de l'onglet Transferts en sélectionnant le transfert souhaité :

télécharger des données historiques

Astuce 2. Si vous souhaitez vérifier le nombre de comptes Google Ads pour lesquels GCP facturera, vous devez déterminer le nombre d'ID de client externe dans le tableau Client à l'aide de la requête :

    SELECT ExternalCustomerId FROM `project_name.dataset_name.Customer_*` WHERE _PARTITIONTIME >= "2020-01-01 00:00:00" AND _PARTITIONTIME < "2020-07-10 00:00:00" group by 1
SELECT ExternalCustomerId FROM `project_name.dataset_name.Customer_*` WHERE _PARTITIONTIME >= "2020-01-01 00:00:00" AND _PARTITIONTIME < "2020-07-10 00:00:00" group by 1

Vous pouvez modifier les dates dans la requête.

Astuce 3. Vous pouvez accéder vous-même aux données téléchargées à l'aide de requêtes SQL. Voici, par exemple, une requête permettant de déterminer l'efficacité des campagnes à partir des tables "Campaign" et "CampaignBasicStats" dérivées du transfert de données :

    SELECT {source language="sql"} c.ExternalCustomerId, c.CampaignName, c.CampaignStatus, SUM(cs.Impressions) AS Impressions, SUM(cs.Interactions) AS Interactions, {/source} (SUM(cs.Cost) / 1000000) AS Cost FROM `[DATASET].Campaign_[CUSTOMER_ID]` c LEFT JOIN {source language="sql"} {source language="sql"} `[DATASET].CampaignBasicStats_[CUSTOMER_ID]` cs ON (c.CampaignId = cs.CampaignId AND cs._DATA_DATE BETWEEN DATE_ADD(CURRENT_DATE(), INTERVAL -31 DAY) AND DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY)) WHERE c._DATA_DATE = c._LATEST_DATE GROUP BY 1, 2, 3 ORDER BY Impressions DESC
SELECT {source language="sql"} c.ExternalCustomerId, c.CampaignName, c.CampaignStatus, SUM(cs.Impressions) AS Impressions, SUM(cs.Interactions) AS Interactions, {/source} (SUM(cs.Cost) / 1000000) AS Cost FROM `[DATASET].Campaign_[CUSTOMER_ID]` c LEFT JOIN {source language="sql"} {source language="sql"} `[DATASET].CampaignBasicStats_[CUSTOMER_ID]` cs ON (c.CampaignId = cs.CampaignId AND cs._DATA_DATE BETWEEN DATE_ADD(CURRENT_DATE(), INTERVAL -31 DAY) AND DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY)) WHERE c._DATA_DATE = c._LATEST_DATE GROUP BY 1, 2, 3 ORDER BY Impressions DESC

PS Si vous avez besoin d'aide pour télécharger et fusionner des données dans Google BigQuery, nous sommes prêts à vous aider. Inscrivez-vous pour une démo — et nous discuterons des détails.

INSCRIVEZ-VOUS POUR UNE DÉMO