Alert for PMax Search Terms
Receive an alert by email with all metrics for selected search terms in PMax
Start Now!Receive an alert by email with all metrics for selected search terms in PMax
Start Now!
One of the biggest challenges in Performance Max campaign management is understanding the search intent that leads to a click.
It wasn't even possible before. Thankfully, Google allowed us to view this data recently.
This tool utilizes the new functionality.
It's different from other scripts like that PMax Search Terms report.
My solution doesn’t export any data to spreadsheets.
It's an alerting system that sends an email with all metrics for selected search terms in PMax.
a) Monitor brand terms: This way, you'll know if PMax is cannibalizing your brand campaign.
b) Monitor competition in PMax: This way, you'll know if PMax is bidding heavily on your competition (not always a good idea!).
c) Monitor poorly performing terms: You can look at search or standard campaigns and find top-spending search terms with low ROAS or high CPA and add them to the script.
Schedule: daily or weekly (I prefer Monday morning).
/*
Copyright 2023 Krzysztof Bycina, www.LiveAds.pl
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// --------------------------------------- Configuration:
const UNWANTED_SEARCH_TERMS = ["ENTER YOUR KEYWORD HERE e.g. BRAND NAME"];
const CAMPAIGN_LABEL = "ENTER YOUR LABEL HERE";
const EMAIL = "ENTER YOUR E-MAIL HERE";
// --------------------------------------- End of the configuration
function main() {
const campaigns = fetchCampaigns();
const matches = [];
campaigns.forEach(campaign => {
const id = campaign.id;
const name = campaign.name;
const queries = retrieveQueries(id);
const matchingRows = inspectCampaign(queries, name);
if (matchingRows.length > 0) {
matches.push({
campaignName: name,
matchingRows: matchingRows
});
}
});
if (matches.length > 0) {
notifyByEmail(matches);
}
}
function retrieveQueries(id) {
const query = AdsApp.report(`
SELECT
campaign_search_term_insight.category_label,
metrics.clicks,
metrics.impressions,
metrics.conversions,
metrics.conversions_value
FROM campaign_search_term_insight
WHERE
segments.date DURING LAST_30_DAYS
AND campaign_search_term_insight.campaign_id = '${id}'
ORDER BY metrics.conversions
`);
return query;
}
function inspectCampaign(query, campaignName) {
const data = [];
const rows = query.rows();
while (rows.hasNext()) {
const row = rows.next();
const rowData = {
campaign_name: campaignName,
category_label: row['campaign_search_term_insight.category_label'],
clicks: row['metrics.clicks'],
impressions: row['metrics.impressions'],
conversions: row['metrics.conversions'],
conversions_value: row['metrics.conversions_value']
};
data.push(rowData);
}
const matchingRows = data.filter(row => {
return UNWANTED_SEARCH_TERMS.some(term => row.category_label.includes(term));
});
console.log("PMax campaigns with unwanted search terms: '" + campaignName + "':", matchingRows);
return matchingRows;
}
function notifyByEmail(matches) {
const subject = "PMax search terms alert summary.";
let message = "PMax campaigns with unwanted search terms:\n\n";
let totalClicks = 0;
let totalImpressions = 0;
let totalConversions = 0;
let totalConversionsValue = 0;
matches.forEach(match => {
const campaignName = match.campaignName;
const matchingRows = match.matchingRows;
matchingRows.forEach(row => {
const clicks = parseInt(row.clicks);
const impressions = parseInt(row.impressions);
totalClicks += clicks;
totalImpressions += impressions;
totalConversions += parseFloat(row.conversions);
totalConversionsValue += parseFloat(row.conversions_value);
message += "Campaign: " + campaignName + "\n\n";
message += "Category Label: " + row.category_label + "\n";
message += "Clicks: " + clicks + "\n";
message += "Impressions: " + impressions + "\n";
message += "Conversions: " + parseFloat(row.conversions).toFixed(2) + "\n";
message += "Conversions Value: " + parseFloat(row.conversions_value).toFixed(2) + "\n\n";
});
message += "---------------------------------------------------\n\n";
});
totalConversions = totalConversions.toFixed(2);
totalConversionsValue = totalConversionsValue.toFixed(2);
message = `Total Clicks: ${totalClicks}\n` +
`Total Impressions: ${totalImpressions}\n` +
`Total Conversions: ${totalConversions}\n` +
`Total Conversions Value: ${totalConversionsValue}\n\n` + message;
MailApp.sendEmail(EMAIL, subject, message);
}
function fetchCampaigns() {
const campaigns = [];
const selector = AdsApp.performanceMaxCampaigns()
.withCondition("LabelNames CONTAINS_ANY ['" + CAMPAIGN_LABEL + "']")
.withCondition("Status = ENABLED")
.forDateRange("TODAY");
const iterator = selector.get();
while (iterator.hasNext()) {
const campaign = iterator.next();
campaigns.push({
id: campaign.getId(),
name: campaign.getName()
});
}
return campaigns;
}