Skip to content

Commit 4a30ccc

Browse files
[Components] google_search_console : add “Retrieve Site Performance” & “Submit URL for Indexing” actions (#16378)
* Add GSC Actions : Retrieve Site Perfomance Data & Submit Url For Indexing * Minor fixes: addressed CodeRabbit comments * Minor fixes: addressed CodeRabbit comments * Fix minor CodeRabbit suggestions * Fix minor CodeRabbit suggestions * updates/formatting * pnpm-lock.yaml * move tests to common folder * updates --------- Co-authored-by: michelle0927 <michellelbergero@hotmail.com>
1 parent c4260a5 commit 4a30ccc

18 files changed

+1658
-1
lines changed

components/google_search_console/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,10 @@ The Google Search Console API opens a treasure trove of data and insights about
99
- **Sync Search Results with Google Sheets**: Create a workflow that periodically pulls data from the Google Search Console API and adds it to a Google Sheet. This is useful for maintaining an evolving dataset for deeper analysis, historical reference, or sharing insights across teams without giving direct access to the Search Console.
1010

1111
- **Automatic Sitemap Submission**: Set up a Pipedream workflow that triggers whenever a new sitemap is generated in your content management system (CMS). The workflow can then automatically submit the sitemap to Google Search Console via API, ensuring Google has the latest structure of your site for crawling and indexing.
12+
13+
## Available Actions
14+
15+
[Retrieve Site Performance Data](./actions/retrieve-site-performance-data/README.md)
16+
[Submit URL for Indexing](./actions/submit-url-for-indexing/README.md)
17+
18+
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Google Search Console – Site Performance (Analytics) Action
2+
3+
This action queries **search performance data** for a verified website using the [Google Search Console API](https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query). It allows you to extract insights like:
4+
5+
- Top search queries
6+
- Click-through rates
7+
- Page impressions
8+
- Device types, countries, and more
9+
10+
---
11+
12+
## Use Cases
13+
14+
- Automate SEO reporting
15+
- Analyze organic search trends
16+
- Filter and break down traffic by dimensions (e.g. query, device, country)
17+
18+
---
19+
20+
## Internals
21+
22+
- Supports all relevant props from the [Search Analytics Query API](https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query)
23+
- Trims and validates all input props
24+
- Accepts optional `dimensionFilterGroups` either as an object or JSON string
25+
- Automatically builds the POST request body using `propsMeta` metadata
26+
- Returns the raw Search Console API response for full access to metrics
27+
- Accumulates and displays warnings for non-blocking input issues
28+
29+
---
30+
31+
## Auth
32+
33+
Requires OAuth 2.0 with the following scope: `https://www.googleapis.com/auth/webmasters.readonly`
34+
35+
36+
## Endpoint
37+
`https://searchconsole.googleapis.com/webmasters/v3/sites/{siteUrl}/searchAnalytics/query`
38+
39+
40+
## 📦 Example Request Payload
41+
42+
43+
44+
```json
45+
{
46+
47+
"siteUrl": "https://falc1.com/page",
48+
49+
"startDate": "2025-12-22",
50+
51+
"endDate": "2025-12-31",
52+
53+
"dimensions": ["query", "page", "country", "device"],
54+
55+
"searchType": "web",
56+
57+
"rowLimit": 10,
58+
59+
"startRow": 0,
60+
61+
"aggregationType": "auto",
62+
63+
"dataState": "final",
64+
65+
"dimensionFilterGroups": [
66+
{
67+
68+
"groupType": "and",
69+
70+
"filters": [
71+
{
72+
73+
"dimension": "query",
74+
75+
"operator": "contains",
76+
77+
"expression": "example"
78+
},
79+
{
80+
"dimension": "country",
81+
82+
"operator": "equals",
83+
84+
"expression": "USA"
85+
}
86+
]
87+
}
88+
]
89+
}
90+
```
91+
92+
### Field Descriptions
93+
94+
**siteUrl**: The site you want to query data for. Must be verified in your Google Search Console account.
95+
**startDate**: The start date of the reporting period (inclusive), in YYYY-MM-DD format.
96+
**endDate**: The end date of the reporting period (inclusive), in YYYY-MM-DD format.
97+
**dimensions**: The dimensions you want to break down the data by. Valid values: "query", "page", "country", "device", "searchAppearance", "date". Order matters — it affects how rows are grouped in the response.
98+
**searchType**: The type of search data to include. Valid values: "web", "image", "video", "news", "googleNews", "discover"
99+
**rowLimit**: Maximum number of rows to return (1–25,000)
100+
**startRow**: Optional: Skips the first N rows — used for pagination.
101+
**aggregationType**: Optional: How to group data. "auto" = Google's default grouping. "byPage" = Group by page (useful for getting per-page breakdowns).
102+
**dataState**: Optional: Data freshness filter. "final" = Only finalized data (more accurate). "all" = Includes fresh but possibly incomplete data.
103+
**dimensionFilterGroups**: Optional filter group(s) to restrict which rows are returned. Each group applies logical AND/OR across its filters.
104+
**groupType**: Logical grouping operator for the filters inside this group. "and" = all filters must match, "or" = any filter can match
105+
**filters**: List of individual filters to apply within the group
106+
**dimension**: Which dimension to filter by (must match a dimension in your request)
107+
**operator**: Filter operator — e.g., "equals", "contains", "notEquals", etc.
108+
**expression**: Value to match against
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/**
2+
* Fetches performance data (clicks, impressions, etc.) for a verified site
3+
* via the Google Search Console Search Analytics API.
4+
*
5+
* Full usage docs in README.md
6+
*/
7+
8+
import { axios } from "@pipedream/platform";
9+
import gsConsole from "../../google_search_console.app.mjs";
10+
import {
11+
removeCustomPropFields, trimIfString,
12+
} from "../../common/utils.mjs";
13+
14+
/*
15+
Define prop metadata separately, including custom fields used for extended validation
16+
and runtime behavior.
17+
18+
These extended fields (like `extendedType`, `postBody`, etc.) are not part of the standard
19+
Pipedream prop schema.
20+
21+
A helper function (`removeCustomPropFields`) will later strip these non-standard fields,
22+
returning only valid Pipedream props for use in the UI.
23+
24+
Keeping the full metadata in closure allows access to helpful context (e.g. validation rules)
25+
during runtime.
26+
*/
27+
const propsMeta = {
28+
29+
siteUrl: {
30+
type: "string",
31+
extendedType: "url",
32+
label: "Verified Site URL",
33+
description: "Including https:// is strongly advised",
34+
},
35+
startDate: {
36+
type: "string",
37+
extendedType: "YYYY-MM-DD",
38+
label: "Start Date (YYYY-MM-DD)",
39+
postBody: true,
40+
},
41+
endDate: {
42+
type: "string",
43+
extendedType: "YYYY-MM-DD",
44+
label: "End Date (YYYY-MM-DD)",
45+
postBody: true,
46+
},
47+
dimensions: {
48+
type: "string[]",
49+
label: "Dimensions",
50+
optional: true,
51+
description: "e.g. ['query', 'page', 'country', 'device']",
52+
postBody: true,
53+
},
54+
searchType: {
55+
type: "string",
56+
label: "Search Type",
57+
optional: true,
58+
options: [
59+
"web",
60+
"image",
61+
"video",
62+
"news",
63+
"googleNews",
64+
"discover",
65+
],
66+
default: "web",
67+
postBody: true,
68+
},
69+
aggregationType: {
70+
type: "string",
71+
label: "Aggregation Type",
72+
optional: true,
73+
options: [
74+
"auto",
75+
"byPage",
76+
],
77+
postBody: true,
78+
},
79+
rowLimit: {
80+
type: "integer",
81+
label: "Max rows to return",
82+
default: 10,
83+
postBody: true,
84+
},
85+
startRow: {
86+
type: "integer",
87+
label: "Start row (for pagination)",
88+
optional: true,
89+
postBody: true,
90+
},
91+
dimensionFilterGroups: {
92+
type: "object",
93+
label: "Dimension Filters",
94+
optional: true,
95+
description: "Follow Search Console API structure for filters",
96+
postBody: true,
97+
},
98+
dataState: {
99+
type: "string",
100+
label: "Data State",
101+
optional: true,
102+
options: [
103+
"all",
104+
"final",
105+
],
106+
default: "final",
107+
postBody: true,
108+
},
109+
};
110+
111+
export default {
112+
name: "Retrieve Site Performance Data",
113+
description: "Fetches search analytics from Google Search Console for a verified site.",
114+
key: "google_search_console-retrieve-site-performance-data",
115+
version: "0.0.1",
116+
type: "action",
117+
props: {
118+
gsConsole,
119+
// Remove non-standard fields and expose only valid props to Pipedream UI
120+
...removeCustomPropFields(propsMeta),
121+
},
122+
123+
//=================== RUN ==============================
124+
//======================================================
125+
126+
async run({ $ }) {
127+
128+
/*
129+
`dimensionFilterGroups` is expected to be an object.
130+
If a JSON string is passed instead (e.g. from UI input), attempt to parse it.
131+
- Returns parsed object if successful
132+
- Returns original input if not a string
133+
- Throws a descriptive error if JSON parsing fails
134+
*/
135+
this.dimensionFilterGroups = this.gsConsole.parseIfJsonString(this.dimensionFilterGroups);
136+
137+
// Prepare the POST request payload
138+
const body = {};
139+
140+
// Accumulator for non-blocking input warnings
141+
const warnings = [];
142+
143+
/*
144+
This loop:
145+
- Trims and validates all defined props
146+
- Skips empty optional fields
147+
- Accumulates non-blocking warnings
148+
- Adds valid props to the POST request payload (`body`) if marked with `postBody: true`
149+
*/
150+
for (let propName in propsMeta) {
151+
152+
// Just for convenience.
153+
const meta = propsMeta[propName];
154+
155+
// Trim the value if it's a string
156+
this[propName] = trimIfString(this[propName]);
157+
158+
// Skip if the prop is optional and empty (null, undefined, or blank string)
159+
if (meta.optional === true && ((this[propName] ?? "") === "")) continue;
160+
161+
// Validate input (may throw or return warning messages)
162+
const validationResult = this.gsConsole.validateUserInput(meta, this[propName]);
163+
164+
// Push the warnings into warnings accumulator if any.
165+
if (validationResult.warnings) warnings.push(...validationResult.warnings);
166+
167+
// Include prop in the request body if marked as postBody
168+
if (meta.postBody === true) body[propName] = this[propName];
169+
};
170+
171+
// Already trimmed earlier
172+
const url = this.siteUrl;
173+
174+
// Response of the POST request.
175+
let response;
176+
177+
try {
178+
response = await axios($, {
179+
method: "POST",
180+
url: `https://searchconsole.googleapis.com/webmasters/v3/sites/${encodeURIComponent(url)}/searchAnalytics/query`,
181+
headers: {
182+
"Authorization": `Bearer ${this.gsConsole.$auth.oauth_access_token}`,
183+
"Content-Type": "application/json",
184+
},
185+
data: body,
186+
});
187+
188+
} catch (error) {
189+
// Identify if the error was thrown by internal validation or by the API call
190+
const thrower = this.gsConsole.checkWhoThrewError(error);
191+
192+
throw new Error(`Failed to fetch data ( ${thrower.whoThrew} error ) : ${error.message}. ` + warnings.join("\n- "));
193+
};
194+
195+
// Output summary and any warnings for the user
196+
$.export("$summary", ` Fetched ${response.rows?.length || 0} rows of data. ` + warnings.join("\n- "));
197+
return response;
198+
},
199+
};
200+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# 🚀 Google Indexing API – URL Submission Action
2+
3+
This action submits a specific URL to the **Google Indexing API** to notify Google that the content has been **updated** and should be re-crawled.
4+
5+
---
6+
7+
## ✅ Use Case
8+
9+
Use this action when:
10+
- You’ve updated content on a page
11+
- You want to request Google to reindex that URL as soon as possible
12+
13+
---
14+
15+
## 🧠 Internals
16+
17+
- Validates and trims the input URL
18+
- Uses the `URL_UPDATED` type to inform Google of a content change
19+
- Returns the raw API response
20+
- Displays a user-friendly summary
21+
- Accumulates and returns non-blocking warnings (e.g. unusual characters in the URL)
22+
23+
---
24+
25+
## 🔐 Auth
26+
27+
+Requires OAuth 2.0 with [indexing](https://www.googleapis.com/auth/indexing) scope:
28+
29+
## 🔗 Endpoint
30+
31+
[https://indexing.googleapis.com/v3/urlNotifications:publish](https://www.googleapis.com/auth/indexing)

0 commit comments

Comments
 (0)