效果最大化广告系列因其自动化和简便性而在PPC广告客户中广受欢迎。然而,一个持续存在的痛点是缺乏对触发广告的搜索查询的可见性。如果没有这些数据,效果最大化广告系列的优化就会受到限制。
2023 年 2 月,谷歌推出了campaign_search_term_insight报告,其中包含一个包含搜索词的字段,这似乎让人松了一口气。包括我在内的脚本开发人员立即使用这些新的搜索词数据为 Performance Max 广告系列构建了脚本和自动化程序。
然而,尽管许多发布的脚本声称包含搜索词数据,但它们均未包含搜索词数据;相反,它们仅限于类别标签。这是由于 Google 报告一直存在错误,拒绝包含搜索词数据。
感谢 Mike Rhodes 监控 Google 报告并告知我该错误最近已得到解决。现在搜索词数据终于可以在脚本中使用了,我将解释如何访问搜索查询数据、对其进行分析以找到优化机会并根据结果采取行动。
目前有哪些数据可用?
2023 年 2 月,Google 推出了一份新的洞察报告,专门用于展示 Performance Max 搜索字词数据。此报告可让您了解以下内容:
- 您的广告实际出现的搜索查询。
- 将查询分组到的搜索类别。
- 点击次数、展示次数和其他绩效指标。
它无法提供成本的可见性。但是,拥有搜索词和点击量是一大进步。
访问数据
有以下几种方法可以访问新的 Performance Max 搜索洞察报告:
- 直接在 Google Ads 界面的广告系列页面的Insights下进行。
- 通过 Google Ads API。
- 使用利用 API 报告的 Google Ads 脚本。

使用脚本的好处是它可以自动将数据拉入电子表格,以便于操作和分析。
我创建了一个脚本,将搜索词放入电子表格中。只需转到此要点 URL并复制代码即可。
然后将其粘贴到 Google Ads Scripts 界面。然后,它会自动将所有 Performance Max 广告系列的搜索词数据提取到 Google Sheet 中。
当您运行脚本时,它会将数据添加到电子表格中,如下所示:
数据可用性与常规搜索查询报告类似,但有一些限制:
- 数据仅可追溯至 2023 年 3 月首次发布之时。
- 如果搜索量很大,可能会对搜索词数据进行采样。
不过,这仍然比之前的效果最大化广告系列提供了更高的可见度。
分析数据
现在您已将效果最大化搜索查询数据提取到电子表格中,您可以获得哪些见解?以下是您可以进行的一些分析:
识别触发您的广告的不相关搜索词。
- 查找可提高转化率的高效搜索词。寻找机会优化这些词以增加搜索量。
- 查看搜索类别,寻找已在起作用的其他关键字创意。
- 按展示次数排序,可以找到展示次数高、点击次数低的字词,这些字词可能表明相关性较差,并且可以从标题和描述等更好的广告创意资产中受益。
本质上,您正在寻找数据中的搜索词模式,以便更好地优化广告系列。
由于您无法在 Performance Max 中定位特定关键字,因此这并不是要确定要添加的强效新关键字。不过,您可以找到新否定词的信号,并获得有关如何改进广告文案或着陆页的灵感。
使用 GPT-4 分析数据
在谷歌修复错误并使数据正常运行的一年里,GPT 取得了长足的进步。因此,我下载了脚本生成的报告,将 CSV 上传到 GPT-4,并询问它是否可以帮助我找到优化思路。
我使用了提示:
- “我有一个文件,其中包含我在 Performance Max 广告系列中投放的 Google 广告的搜索字词。您能分析一下这些搜索字词并分享一些有趣的发现吗?”
它自动使用 openAI 代码解释器功能来扫描文件,并建议四个数据段供进一步调查:
- 高转化率字词:带来最多转化的搜索字词。
- 高价值字词:转化价值最高的搜索字词。
- 效率指标:点击次数与展示次数之比(CTR)和转化次数与点击次数之比(转化率)最高的搜索词。
- 类别和子类别洞察:不同类别和子类别之间的性能趋势。
它立即开始分析我上传的完整数据集。由于它使用了高级数据分析(以前称为代码解释器),所以我可以看到它正在使用的 Python 代码。
基于此,我发现谷歌在与“免费广告”相关的搜索中大量展示我的广告,由于我对此无能为力,它为我提供了一个新帐户级否定关键字的好主意。
采取行动
现在您已经分析了 Performance Max 搜索字词数据,我建议您采取以下三项措施:
- 将不相关的字词添加为帐户级否定关键字。您无法在效果最大化广告系列级别添加否定关键字。但是,将不相关的字词添加为帐户否定词将阻止广告在整个帐户中针对这些查询展示。
- 针对效果良好的查询优化广告和登录页面。寻找点击率和转化率较高的搜索词主题。然后,增强您的广告文案、优惠和登录页面,以更好地定位这些用户。
- 利用您了解到的信息优化受众定位。搜索查询可让您深入了解理想受众。寻找可作为受众目标添加到广告系列中的人口统计或兴趣模式。
脚本
function main() { | |
/****************************************** | |
* PMax Search Terms Report | |
* @version: 1.0 | |
* @authors: Frederick Vallaeys (Optmyzr) | |
* ——————————- | |
* Install this script in your Google Ads account (not an MCC account) | |
* to generate a spreadsheet containing the search terms in your Performance Max campaigns. | |
* The spreadsheet also includes data about category labels (groupings of search terms). | |
* Metrics include conversion value, conversions, clicks, and impressions | |
* ——————————– | |
* v2 (Mar 14, 2024): adds a new column that says if the search terms exists as a keyword in a search campaign. adds better error handling. | |
* ——————————– | |
* For more PPC tools and scripts, visit www.optmyzr.com. | |
******************************************/ | |
var minImp = 10; // Limit the output to only items with at least this many impressions | |
var spreadsheetUrl = “”; // leave blank to generate a new spreadsheet or add your own URL to overwrite the data in an existing spreadsheet | |
var reportLastNDays = 30; // The number of days to include in the report | |
var EMAILADDRESS = “”; // enter your email address | |
// Don’t edit below this line unless you know how to write scripts | |
//—————————————————————– | |
let pmaxOnly = 1; | |
let allCategoryLabels = [ | |
[ | |
“Campaign Name”, | |
“Category Label”, | |
“Conv Val”, | |
“Conv”, | |
“Clicks”, | |
“Imp”, | |
], | |
]; | |
let allSearchTerms = [ | |
[ | |
“Campaign Name”, | |
“Category Label”, | |
“Subcat”, | |
“Search Term”, | |
“Conv Val”, | |
“Conv”, | |
“Clicks”, | |
“Imp”, | |
“Exists as Keyword?”, | |
], | |
]; | |
let keywordsList = getAllSearchCampaignKeywords(); | |
var dateRange = getDateRange(reportLastNDays); | |
try { | |
let baseQuery = ` | |
SELECT | |
campaign.id, | |
campaign.name, | |
metrics.clicks, | |
metrics.impressions, | |
metrics.conversions, | |
metrics.conversions_value | |
FROM campaign | |
WHERE campaign.status != ‘REMOVED’ | |
AND metrics.impressions > 0 | |
AND segments.date BETWEEN ${dateRange} | |
AND metrics.impressions >= ${minImp} | |
`; | |
// Modify the SQL query if pmaxOnly is true | |
if (pmaxOnly) { | |
baseQuery += | |
” AND campaign.advertising_channel_type = ‘PERFORMANCE_MAX’ “; | |
} | |
baseQuery += “ORDER BY metrics.conversions DESC”; | |
let campaignIdsQuery = AdsApp.report(baseQuery); | |
let rows = campaignIdsQuery.rows(); | |
while (rows.hasNext()) { | |
let campaignRow = rows.next(); | |
let campaignId = campaignRow[“campaign.id”]; | |
Logger.log( | |
campaignRow[“campaign.id”] + ” ” + campaignRow[“campaign.name”] | |
); | |
// Search Labels Report | |
let categoryLabelsQuery = ` | |
SELECT | |
campaign_search_term_insight.category_label, | |
campaign_search_term_insight.id, | |
metrics.clicks, | |
metrics.impressions, | |
metrics.conversions, | |
metrics.conversions_value | |
FROM | |
campaign_search_term_insight | |
WHERE | |
segments.date BETWEEN ${dateRange} | |
AND campaign_search_term_insight.campaign_id = ‘${campaignId}’ | |
AND metrics.impressions >= ${minImp} | |
ORDER BY | |
metrics.conversions DESC | |
`; | |
let categoryLabelsQueryResult = AdsApp.report(categoryLabelsQuery); | |
let categoryLabelsResults = categoryLabelsQueryResult.rows(); | |
while (categoryLabelsResults.hasNext()) { | |
let categoryLabelsRow = categoryLabelsResults.next(); | |
let categoryLabelId = | |
categoryLabelsRow[“campaign_search_term_insight.id”]; | |
//Logger.log(categoryLabelId + “. ” + categoryLabelsRow[‘campaign_search_term_insight.category_label’] + ” ” + categoryLabelsRow[‘metrics.impressions’]); | |
allCategoryLabels.push([ | |
campaignRow[“campaign.name”], | |
categoryLabelsRow[ | |
“campaign_search_term_insight.category_label” | |
], | |
categoryLabelsRow[“metrics.conversions_value”].toFixed(2), | |
categoryLabelsRow[“metrics.conversions”].toFixed(1), | |
categoryLabelsRow[“metrics.clicks”], | |
categoryLabelsRow[“metrics.impressions”], | |
]); | |
// Search Terms Report | |
let searchTermsQuery = ` | |
SELECT | |
metrics.clicks, | |
metrics.impressions, | |
metrics.conversions, | |
metrics.conversions_value, | |
segments.search_term, | |
segments.search_subcategory | |
FROM | |
campaign_search_term_insight | |
WHERE | |
segments.date BETWEEN ${dateRange} | |
AND campaign_search_term_insight.campaign_id = ‘${campaignId}’ | |
AND campaign_search_term_insight.id = ‘${categoryLabelId}’ | |
`; | |
let searchTermsQueryResult = AdsApp.report(searchTermsQuery); | |
let searchTermsResults = searchTermsQueryResult.rows(); | |
// Inside the loop where search terms are being processed | |
while (searchTermsResults.hasNext()) { | |
let searchTermsRow = searchTermsResults.next(); | |
if (searchTermsRow[“metrics.impressions”] >= minImp) { | |
let searchTermText = searchTermsRow[ | |
“segments.search_term” | |
].toLowerCase(); // Normalize search term text for comparison | |
let existsAsKeyword = keywordsList[searchTermText] | |
? “Yes” | |
: “No”; | |
allSearchTerms.push([ | |
campaignRow[“campaign.name”], | |
categoryLabelsRow[ | |
“campaign_search_term_insight.category_label” | |
], | |
searchTermsRow[“segments.search_subcategory”], | |
searchTermsRow[“segments.search_term”], | |
searchTermsRow[“metrics.conversions_value”].toFixed( | |
2 | |
), | |
searchTermsRow[“metrics.conversions”].toFixed(1), | |
searchTermsRow[“metrics.clicks”], | |
searchTermsRow[“metrics.impressions”], | |
existsAsKeyword, // New column indicating if the search term exists as a keyword | |
]); | |
} | |
} | |
} | |
} | |
if (!spreadsheetUrl) { | |
var ss = SpreadsheetApp.create(“PMax Search Terms”, 10000, 20); | |
var spreadsheetUrl = ss.getUrl(); | |
} else { | |
var ss = SpreadsheetApp.openByUrl(spreadsheetUrl); | |
} | |
let categoriesSheet = ss.getSheetByName(“categories”) | |
? ss.getSheetByName(“categories”).clear() | |
: ss.insertSheet(“categories”); | |
if (allCategoryLabels.length > 1) { | |
// Check if there’s more than just the header row | |
categoriesSheet | |
.getRange( | |
1, | |
1, | |
allCategoryLabels.length, | |
allCategoryLabels[0].length | |
) | |
.setValues(allCategoryLabels); | |
} | |
let termsSheet = ss.getSheetByName(“terms”) | |
? ss.getSheetByName(“terms”).clear() | |
: ss.insertSheet(“terms”); | |
if (allSearchTerms.length > 1) { | |
// Check if there’s more than just the header row | |
termsSheet | |
.getRange(1, 1, allSearchTerms.length, allSearchTerms[0].length) | |
.setValues(allSearchTerms); | |
} | |
var subject = “PMax Search Terms Report Ready”; | |
var body = | |
“The PMax Search Terms Report has been generated and is available at: ” + | |
spreadsheetUrl + | |
“\n\nReport covers the last ” + | |
reportLastNDays + | |
” days.” + | |
“\n\nThis is an automated email sent by Google Ads Script.”; | |
} catch (e) { | |
Logger.log(“Error: ” + e.message); | |
var subject = “PMax Search Terms Report Failed”; | |
var body = | |
“The PMax Search Terms Report encountered an error: ” + | |
e + | |
“\n\nThis is an automated email sent by Google Ads Script.”; | |
} | |
Logger.log(“spreadsheet: ” + spreadsheetUrl); | |
// Send the email | |
var recipientEmail = EMAILADDRESS; | |
MailApp.sendEmail(recipientEmail, subject, body); | |
} | |
// function to get date range | |
function getDateRange(numDays) { | |
const endDate = new Date(); | |
const startDate = new Date(); | |
startDate.setDate(endDate.getDate() – numDays); | |
const format = (date) => | |
Utilities.formatDate( | |
date, | |
AdsApp.currentAccount().getTimeZone(), | |
“yyyyMMdd” | |
); | |
return `${format(startDate)} AND ${format(endDate)}`; | |
} | |
function getAllSearchCampaignKeywords() { | |
let keywordsList = {}; | |
let keywordIterator = AdsApp.keywords() | |
.withCondition(“Status = ENABLED”) | |
.withCondition(“CampaignStatus = ENABLED”) | |
.withCondition(“AdGroupStatus = ENABLED”) | |
.get(); | |
while (keywordIterator.hasNext()) { | |
let keyword = keywordIterator.next(); | |
let keywordText = keyword.getText().toLowerCase(); // Normalize keyword text for comparison | |
keywordsList[keywordText] = true; // Use a map for efficient lookup | |
} | |
return keywordsList; | |
} |
使用 Performance Max 搜索词来提升 PPC 结果
Performance Max 搜索词可见度的发布已经酝酿已久。这些数据最终赋予 PPC 广告主对自动化广告系列更多的控制和优化能力。
作为 PPC 专家,请务必立即利用这一新功能。按照我们的指导访问和分析数据,然后根据所获的见解采取行动。随着时间的推移,您将更清楚地了解您的 Performance Max 广告覆盖了哪些人,以及如何改进您的信息以引起受众的共鸣。
其结果是,广告将更具相关性、成本更低,而且最重要的是,您的效果最大化广告系列将带来更多的转化。
作者附言:与所有脚本一样,一些用户报告了错误。我知道当单个搜索主题不返回任何搜索词数据时会出现错误,并且我已修改已发布的脚本以改进其处理此类错误的方式。请在 GitHub上留下您对此脚本问题的评论 ,以便我尽力帮助您。”
我们邀请投稿作者为 Search Engine Land 撰写内容,并根据他们的专业知识和对搜索社区的贡献进行选择。我们的投稿者在编辑人员的监督下工作,并检查投稿的质量和与读者的相关性。他们表达的观点是他们自己的。