Productivity · 0 triggers · 8 actions
Tools and reports help you measure your site's Search traffic Add Google Search Console to your Stream Deck workflows with guided setup for the connection details it needs.
Add Google Search Console to a workflow and pair it with a Stream Deck button to run it in one press — handy for productivity tasks. Combine it with OBS, your Elgato tools, or any other app you connect to build a routine that fits how you work.
Browse all templatesSteps your workflow can perform in Google Search Console.
Sends a URL_UPDATED or URL_DELETED notification for one page to Google's Indexing API (indexing.googleapis.com) — a SEPARATE API from Search Console reporting.
Use only for pages carrying JobPosting or BroadcastEvent (livestream `VideoObject`) structured data — Google supports nothing else: a job listing that was posted, changed or filled, or a livestream page going live or ending. Default quota is 200 notifications per day per project, and the connected account must be a verified owner of the site.
Do NOT use it to "request indexing" an ordinary page — no API does that. The "Request indexing" button in the Search Console UI has no API equivalent, and calling this for a normal page does not get it crawled sooner; Google ignores or rejects notifications for pages without the supported structured data. When a user asks you to request indexing, recrawl or "push" an ordinary page, say that no API can do it and offer the two real options instead: Submit Sitemap to have Google re-read the sitemap containing the page, and Inspect URLs to check its current index status and last crawl time.
Returns Google's urlNotificationMetadata: the notified url plus latestUpdate / latestRemove objects carrying type and notifyTime. A success means the notification was accepted, NOT that the page was crawled or indexed.
Mistakes. The siteUrl prop is the page URL to notify about, not a property identifier — the name is legacy. Pass a full canonical page URL such as https://www.example.com/jobs/paleobotanist; never sc-domain:example.com or a bare property prefix. Send URL_DELETED only after the page actually returns 404 or 410. Do not burn the 200/day quota on ordinary pages.
View docs
Submits a sitemap (or resubmits one already listed) to Google Search Console for a property, then reads the stored record back. Resubmitting is idempotent — it creates no duplicate, it updates lastSubmitted and sets isPending: true.
Use for a new sitemap, or when the user wants Google to pick up new or changed pages on a site: resubmitting an existing sitemap is the SUPPORTED way to ask Google to re-read it.
There is no API to request indexing of a single ordinary page. The "Request indexing" button in the Search Console UI has no API equivalent, and the Indexing API behind Submit URL for Indexing covers only JobPosting and BroadcastEvent pages. So the two legitimate options are this tool (have Google re-read the sitemap containing the page) and Inspect URLs (check the page's current index status). Say that plainly rather than implying a page can be force-indexed — and when the user asks to request indexing or force a recrawl, OFFER those two options and wait for them to pick one; do not run either unasked.
Returns { submitted: true, sitemap, previous_last_submitted }. The submit call itself returns an empty body, so sitemap is the record read back from Google immediately afterwards and is how you confirm it landed. previous_last_submitted is the lastSubmitted the sitemap had before this call, or null for a first submission — use it to tell a fresh submission from a resubmission. Right after a submit isPending is normally true and lastDownloaded still holds the old date (or is absent): Google fetches asynchronously, usually within minutes to days. So do NOT report a sitemap as "processed" or "indexed" on the strength of a successful submit.
Mistakes. sitemapUrl must be an absolute URL to the sitemap file (https://www.example.com/sitemap.xml) that lives under the property — not a page URL, a path (/sitemap.xml) or a property identifier. If the user has not given you a sitemap URL, ask for it rather than guessing a conventional path. Submitting is not indexing: Google may still choose not to index the URLs it finds. Do not delete and resubmit to "refresh" a sitemap — just resubmit. Requires siteOwner or siteFullUser (check with List Sites); a siteRestrictedUser gets 403.
View docs
Query Google Search Console search analytics for one property and one date range: clicks, impressions, CTR and average position, optionally grouped by dimensions and filtered. This is the main traffic-reporting tool for a site.
Use for any single-date-range question about how a site performs in Google Search — top queries, top pages, country or device splits, daily or hourly trends, the CTR or average position of a term. Use Compare Search Analytics instead for period-over-period questions (month over month, year over year, "did the update hurt us") — it fetches both ranges and joins them for you. Use Inspect URLs for index status, canonicals and crawl state; this tool only reports traffic.
Returns the API response unchanged — rows (each { keys, clicks, impressions, ctr, position }, where keys lines up positionally with dimensions), responseAggregationType and metadata — plus row_count, has_more (the page came back full, so more rows probably exist), next_start_row (pass it back as startRow) and returned_totals (clicks and impressions summed over the RETURNED rows only).
Reading the numbers. ctr is a 0-1 fraction (0.1428 means 14.3%) and position is a 1-indexed float where LOWER is better. Both are impression-weighted, so never re-average them across rows — a plain mean is wrong. returned_totals is not the property total, least of all when grouping by query: Google omits anonymized (rare) queries, so the sum of query rows is materially LESS than the same range grouped by date. For a true total, query with no dimensions or with date. And check has_more before reporting a count or a "top N" — a truncated first page is not the whole answer.
Scoping to one page or segment. Set subdomainFilter — the filter VALUE, despite the legacy prop name — together with filterDimension and filterOperator. For "page X only" that is filterDimension: page, filterOperator: equals, value = the full URL. Selecting a matching URL-prefix property instead is NOT equivalent: a prefix property covers every page under it, so the numbers come back for the whole prefix. Use advancedDimensionFilters for multi-condition filters; it is ignored whenever subdomainFilter is set.
Freshness. The most recent 2-3 days are not final and are omitted under dataState: final (the default), so a range ending today comes back one to three rows short. When the user asks for "the last N days" and every day needs a figure, set dataState: all.
Discover has no `query` dimension (400 "Request for DISCOVER cannot be grouped by query"). When the user asks for Discover queries, do not stop to ask: report Discover pages instead (searchType: discover, dimensions: ["page"]) and say why.
Example. siteUrl="sc-domain:example.com", startDate="2025-09-01", endDate="2026-08-31", dimensions=["query"], rowLimit=10 returns rows such as { keys: ["example brand"], clicks: 41, impressions: 287, ctr: 0.1429, position: 2.4 } plus row_count: 10, has_more: true and next_start_row: 10.
There is no fields parameter — rows are already minimal, so rowLimit plus has_more/next_start_row is the payload lever. Quota: 1,200 queries per minute per site. View docs
Lists every Google Search Console property the connected Google account can access, plus that account's email address.
Call this first on any per-site task, unless the user already gave an exact identifier such as sc-domain:example.com: every other tool needs the identifier byte-for-byte, and it must be copied from here, never constructed. Call it again after a 403 to see what the account really has.
Do NOT call it when Search Console cannot do the task at all — backlinks or the Links report, requesting indexing of an ordinary page, adding or removing property owners. Say that first, and call this only if the user then asks for something the tools do cover.
Returns { account_email, sites: [{ siteUrl, permissionLevel, property_type }], count }, domain properties first then alphabetical. The list is complete — the API has no pagination. property_type is "domain" for an sc-domain: identifier (covers every subdomain and both schemes — prefer it for traffic questions unless the user names a specific prefix) and "url_prefix" otherwise (an exact scheme + host + path prefix, trailing slash included). account_email is null if the email could not be read; the site list still returns.
Permission levels. siteOwner and siteFullUser can submit and delete sitemaps and inspect URLs (only an owner can manage users); siteRestrictedUser is read-only on reports and cannot submit sitemaps or inspect URLs (403); siteUnverifiedUser has no data at all. Check the level here before promising a write.
Mistakes. A URL-prefix identifier with the wrong scheme or subdomain, or missing its trailing slash, returns 403 "User does not have sufficient permission for site" even when the account is authorized — so copy siteUrl verbatim. This action takes no parameters.
View docs
Lists the sitemaps Google Search Console knows about for a property, with their error, warning and freshness state normalized to numbers.
Use for any sitemap question — which are submitted, which have errors or warnings, when Google last downloaded one, how many URLs it contains. Always call it before Delete Sitemap when the user has not named an exact sitemap URL, and after Submit Sitemap or Delete Sitemap to confirm the new state: in both cases leave sitemapUrl empty and look for the path, because a single-path lookup of a deleted or unknown sitemap returns 404.
Not for whether the URLs inside a sitemap are indexed (use Inspect URLs). This tool reports what Google recorded about a sitemap; it does not fetch or parse the XML itself.
Returns { sitemaps: [...], count, summary: { with_errors, with_warnings, pending, never_downloaded } }. path is the full sitemap URL and is the exact string to pass to Submit Sitemap or Delete Sitemap. warnings, errors and submitted_urls are integers here (the raw API returns strings); submitted_urls is the sum of contents[].submitted. isPending: true means Google accepted the sitemap but has not fetched it yet. A sitemap with no lastDownloaded has never been downloaded and is counted in summary.never_downloaded.
Mistakes. Do not guess a sitemap URL — list first and use a path from the result; an unknown path returns 404 "'<url>' is not a submitted or a known sitemap." lastDownloaded can be years old while the sitemap is still valid, so report the date rather than treating it as an error. errors and warnings count sitemap-parsing problems, not indexing problems.
Example. siteUrl="sc-domain:example.com" with no other input returns { count: 3, summary: { with_errors: 1, ... }, sitemaps: [{ path: "https://www.example.com/sitemap.xml", lastDownloaded: "2018-05-06T02:44:10.000Z", errors: 1, warnings: 1, submitted_urls: 2, contents: [{ type: "web", submitted: "2", indexed: "0" }] }, ...] } — so "when was it last downloaded and how many URLs?" is 6 May 2018 and 2 URLs.
View docs
Returns Google's index status, canonical selection and crawl state for 1-10 URLs of one Search Console property in a single call. This is the API behind the URL Inspection tool in the Search Console UI.
Use for "is this page indexed?", "when did Google last crawl it?", "does Google's canonical match the one I declared?", "why is this URL missing from search?", and batch health checks after a deploy or migration — pass every URL you care about in ONE call, not one call per URL.
Not for backlinks. Search Console's Links report has no API at all. referringUrls here is only a small sample of pages Google happened to discover the URL from — not a backlink profile — so when asked for backlinks, call no Search Console tool and say plainly that the links report is not available through the API. The result also carries no Core Web Vitals or page-experience data. And if the user asks to "request indexing" or force a recrawl of an ordinary page, do not run this tool (or any other) on your own initiative: explain that no API does that, OFFER this index-status check or a sitemap resubmission via Submit Sitemap, and wait for them to choose.
Returns { results: [...], summary: { total, indexed, not_indexed, errors } }, one row per URL in the same order as inspectionUrls. Reading the rows:
- verdict is PASS (indexed), NEUTRAL (known but not indexed, or unknown to Google), FAIL or PARTIAL. A URL Google has never seen returns NEUTRAL with a coverageState like "URL is unknown to Google" — that is a valid answer, not an error.
- canonical_mismatch is true when googleCanonical and userCanonical are both present and differ, false when they match, null when either is missing.
- referringUrls is truncated to the first 5; referring_url_count is the full count.
- error is null on success and a message when that single URL failed — one bad URL never aborts the batch. In summary, indexed counts PASS rows, errors counts rows with an error, and not_indexed is everything else.
- The raw API result is attached per row as full_result ONLY when includeFullResult is true. Leave it off unless the user asks for the complete raw result: it is large and mostly rich-results and AMP detail.
Mistakes. A path such as /about is not accepted — send full absolute URLs that live under siteUrl. Each inspection takes Google roughly 5-10 seconds, so a 10-URL batch runs about 20 seconds; that is normal, not a hang. Quota is 2,000 inspections per day AND 600 per minute per property, and a quota error does not say which was hit. Requires siteOwner or siteFullUser — a siteRestrictedUser gets 403, and so does a mismatched siteUrl (URLs outside the property, a missing trailing slash, sc-domain: versus URL-prefix confusion), so copy the identifier verbatim from List Sites.
Example. siteUrl="sc-domain:example.com", inspectionUrls=["https://www.example.com/"] -> results[0] has verdict: "PASS", coverageState: "Submitted and indexed", googleCanonical: "https://www.example.com/", userCanonical: "https://example.com/" and canonical_mismatch: true — Google indexed the www URL even though the page declares the non-www one.
View docs
Unlists a sitemap from a Google Search Console property. Destructive, and not reversible by this tool.
Confirm before calling. Only call it once the user has explicitly confirmed the exact sitemapUrl. If the ask is vague ("remove the old sitemap"), call List Sitemaps first, show the candidate paths and ask which one. If the user names a sitemap but has not confirmed the deletion, state the exact sitemapUrl you are about to delete and ask. Silence is not consent: if you cannot obtain an explicit confirmation in this turn (for example no confirmation prompt is available), end your turn by asking in plain text and do NOT call this tool. Never delete a sitemap as a side effect of another task, and never delete-and-resubmit to "refresh" one — Submit Sitemap on the existing path already does that.
What this does NOT do. It only UNLISTS the sitemap from Search Console. The pages it contained stay in Google's index and remain crawlable, and the sitemap file stays on the website. Do not offer this tool as a way to remove content from Google.
Returns { deleted: true, sitemapUrl } — the API body is empty, so there is nothing else to report. To prove it is gone, call List Sitemaps with NO sitemapUrl and check the path is absent; asking for the deleted path directly returns 404 "'<url>' is not a submitted or a known sitemap.", which reads as an error.
Mistakes. Passing a path (/sitemap.xml) or a guessed URL instead of a path from List Sitemaps returns that same 404 — and so does the https://www. variant when the property lists the http:// one, because host and scheme are part of the identity. Requires siteOwner or siteFullUser; a siteRestrictedUser gets 403.
View docs
Compare Google Search Console traffic between two date ranges for one property and return the deltas. Fetches both periods in parallel, joins the rows on their dimension keys, and reports per-row and total clicks, impressions, ctr and position change — the period-over-period arithmetic is done for you.
Use for any question that compares two date ranges: month over month, quarter over quarter, year over year, "which queries gained or lost the most clicks", "did mobile grow", "did that update hurt us". Use Query Search Analytics for a single date range, for paging past 5000 rows, and for the hour and searchAppearance dimensions this tool does not accept. Property-level vs page-level position questions also need two Query Search Analytics calls with different aggregationType values.
Returns { current_period, previous_period, totals, rows, row_count, has_more, truncated, note }. totals carries current, previous, delta and pct_change for the whole period, computed from every fetched row rather than just the returned ones. Each row is { keys, current, previous, delta, pct_change }.
Reading the deltas. A key present in only one period gets zeros for the other, so new and lost queries both show up — but its delta.ctr and delta.position are null, because the missing period has no CTR or position to compare against (delta.clicks and delta.impressions are still real numbers). pct_change is null where the previous period was zero — not 0 and not infinity. ctr is a 0-1 fraction (0.1428 means 14.3%) and position is 1-indexed where lower is better, so a NEGATIVE position delta is an improvement; both are impression-weighted, so never re-average them across rows. Query rows always understate the real total because Google omits anonymized (rare) queries — compare with no dimensions, or by date, for true totals. truncated is true when either period hit the internal 5000-row cap, so rows and totals may be incomplete: narrow the range or add a filter. has_more is a different signal — it only means the join produced more rows than rowLimit. note warns about anonymized queries when relevant, otherwise it is null.
Mistakes. "The previous period" means the same number of days immediately before the current period: for 2026-08-01..2026-08-28 (28 days) that is 2026-07-04..2026-07-31. "The same period last year" means both dates shifted back one year. Grouping Discover by query returns a 400 — Discover has no query dimension. Comparing a range that ends today makes the current period look artificially low, because data is final only after about 2-3 days unless dataState is all. filterValue (with filterDimension/filterOperator) is applied identically to both periods and wins over advancedDimensionFilters; the equivalent prop on Query Search Analytics is named subdomainFilter for backwards compatibility.
Example. siteUrl="sc-domain:example.com", currentStartDate="2026-08-01", currentEndDate="2026-08-28", previousStartDate="2026-07-04", previousEndDate="2026-07-31", dimensions=["query"], sortBy="clicks_delta" returns totals: { current: { clicks: 74, ... }, previous: { clicks: 68, ... }, delta: { clicks: 6, ... }, pct_change: { clicks: 0.0882, ... } } and rows such as { keys: ["example brand"], current: { clicks: 41, ... }, previous: { clicks: 33, ... }, delta: { clicks: 8, ... } }.
View docs
Tools and reports help you measure your site's Search traffic
Create your Conductor Deck account: no credit card required.
Follow the setup prompts for Google Search Console. Conductor Deck handles the app authorization or required connection details inside the workflow builder.
Add a Google Search Console action to your visual workflow canvas. Configure the options you need, then connect it to other steps.
Sync your workflow to any Stream Deck button. Press once to trigger the entire sequence.
Sign up for free and start building Google Search Console workflows in minutes.