{ "kind": "open-flow-workflow", "version": 1, "name": "Email a Weekly Search Console Report", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_d98c8474e0ed9efb": { "name": "Monday at 07:00 UTC", "kind": "cron", "cronTimes": [ { "type": "cron", "expression": "0 7 * * 1", "timezone": "UTC" } ] }, "n_cbf9b8ae62f5dbdc": { "inputs": {}, "name": "Set the reporting dates", "kind": "task", "task": { "inputs": [], "outputs": [ { "jsonSchema": { "type": "string", "format": "date", "description": "The inclusive start date for the query in YYYY-MM-DD format." }, "nullable": false, "handle": "startDate" }, { "jsonSchema": { "type": "string", "format": "date", "description": "The inclusive end date for the query in YYYY-MM-DD format." }, "nullable": false, "handle": "endDate" } ], "name": "Set the reporting dates", "moduleId": "n_697d89b75025a109", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_9e217dc6d424a2ce": { "inputs": { "siteUrl": { "kind": "value", "value": "https://example.com/" }, "startDate": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_cbf9b8ae62f5dbdc", "output": "startDate" } ] }, "endDate": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_cbf9b8ae62f5dbdc", "output": "endDate" } ] }, "dimensions": { "kind": "value", "value": [ "query" ] }, "rowLimit": { "kind": "value", "value": 10 }, "dataState": { "kind": "value", "value": "final" } }, "name": "Read search performance", "kind": "task", "task": { "inputs": [ { "description": "The site URL exactly as Search Console stores it, such as https://www.example.com/ or sc-domain:example.com.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The site URL exactly as Search Console stores it, such as https://www.example.com/ or sc-domain:example.com." }, "nullable": false, "handle": "siteUrl" }, { "description": "The inclusive start date for the query in YYYY-MM-DD format.", "jsonSchema": { "type": "string", "format": "date", "description": "The inclusive start date for the query in YYYY-MM-DD format." }, "nullable": false, "handle": "startDate" }, { "description": "The inclusive end date for the query in YYYY-MM-DD format.", "jsonSchema": { "type": "string", "format": "date", "description": "The inclusive end date for the query in YYYY-MM-DD format." }, "nullable": false, "handle": "endDate" }, { "description": "Dimensions used to group result rows.", "jsonSchema": { "type": "array", "items": { "type": "string", "enum": [ "date", "hour", "query", "page", "country", "device", "searchAppearance" ], "description": "A Search Analytics dimension to group rows by." }, "description": "Dimensions used to group result rows." }, "nullable": true, "handle": "dimensions", "value": null }, { "description": "The Google search type to query.", "jsonSchema": { "type": "string", "enum": [ "web", "image", "video", "news", "discover", "googleNews" ], "description": "The Google search type to query." }, "nullable": true, "handle": "type", "value": null }, { "description": "Dimension filter groups applied to the query.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "groupType": { "type": "string", "enum": [ "and" ], "description": "How filters in the group are combined." }, "filters": { "type": "array", "items": { "type": "object", "properties": { "dimension": { "type": "string", "enum": [ "date", "hour", "query", "page", "country", "device", "searchAppearance" ], "description": "A Search Analytics dimension to filter by." }, "operator": { "type": "string", "enum": [ "contains", "equals", "notContains", "notEquals", "includingRegex", "excludingRegex" ], "description": "The filter operator to apply to the dimension." }, "expression": { "type": "string", "minLength": 1, "description": "The expression to match against the selected dimension." } }, "required": [ "dimension", "operator", "expression" ], "additionalProperties": false, "description": "A Search Analytics dimension filter." }, "description": "Filters applied within this group." } }, "required": [ "filters" ], "additionalProperties": false, "description": "A group of Search Analytics dimension filters." }, "description": "Dimension filter groups applied to the query." }, "nullable": true, "handle": "dimensionFilterGroups", "value": null }, { "description": "How Search Console aggregates query results.", "jsonSchema": { "type": "string", "enum": [ "auto", "byNewsShowcasePanel", "byPage", "byProperty" ], "description": "How Search Console aggregates query results." }, "nullable": true, "handle": "aggregationType", "value": null }, { "description": "Maximum rows to return. Search Console accepts up to 25,000.", "jsonSchema": { "type": "integer", "minimum": 1, "maximum": 25000, "description": "Maximum rows to return. Search Console accepts up to 25,000." }, "nullable": true, "handle": "rowLimit", "value": null }, { "description": "Zero-based first row offset for pagination.", "jsonSchema": { "type": "integer", "minimum": 0, "description": "Zero-based first row offset for pagination." }, "nullable": true, "handle": "startRow", "value": null }, { "description": "Whether to include fresh or final-only data.", "jsonSchema": { "type": "string", "enum": [ "final", "all", "hourly_all" ], "description": "Whether to include fresh or final-only data." }, "nullable": true, "handle": "dataState", "value": null } ], "outputs": [ { "description": "Rows returned by Search Console.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "keys": { "type": "array", "items": { "type": "string", "description": "A dimension value." }, "description": "Dimension values for this row, in the same order as the requested dimensions." }, "clicks": { "type": "number", "description": "Click count for this row." }, "impressions": { "type": "number", "description": "Impression count for this row." }, "ctr": { "type": "number", "description": "Click-through rate for this row." }, "position": { "type": "number", "description": "Average position for this row." } }, "required": [ "keys", "clicks", "impressions", "ctr", "position" ], "additionalProperties": false, "description": "A Search Analytics result row." }, "description": "Rows returned by Search Console." }, "nullable": false, "handle": "rows" }, { "description": "The aggregation type used in the response when Search Console returns one.", "jsonSchema": { "type": [ "string", "null" ], "description": "The aggregation type used in the response when Search Console returns one." }, "nullable": true, "handle": "responseAggregationType" }, { "description": "Metadata returned with Search Analytics data.", "jsonSchema": { "type": "object", "properties": { "firstIncompleteDate": { "type": [ "string", "null" ], "description": "The first date with incomplete data when Search Console reports one." }, "firstIncompleteHour": { "type": [ "string", "null" ], "description": "The first hour with incomplete hourly data when Search Console reports one." } }, "required": [ "firstIncompleteDate", "firstIncompleteHour" ], "additionalProperties": false, "description": "Metadata returned with Search Analytics data." }, "nullable": false, "handle": "metadata" } ], "name": "Read search performance", "executor": { "kind": "connector", "action": "google_search_console.query_search_analytics" } } }, "n_37531295eefd9dc5": { "inputs": { "rows": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_9e217dc6d424a2ce", "output": "rows" } ] }, "startDate": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_cbf9b8ae62f5dbdc", "output": "startDate" } ] }, "endDate": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_cbf9b8ae62f5dbdc", "output": "endDate" } ] } }, "name": "Prepare the report", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "keys": { "type": "array", "items": { "type": "string", "description": "A dimension value." }, "description": "Dimension values for this row, in the same order as the requested dimensions." }, "clicks": { "type": "number", "description": "Click count for this row." }, "impressions": { "type": "number", "description": "Impression count for this row." }, "ctr": { "type": "number", "description": "Click-through rate for this row." }, "position": { "type": "number", "description": "Average position for this row." } }, "required": [ "keys", "clicks", "impressions", "ctr", "position" ], "additionalProperties": false, "description": "A Search Analytics result row." }, "description": "Rows returned by Search Console." }, "nullable": false, "handle": "rows" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "startDate" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "endDate" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "text" } ], "name": "Prepare the report", "moduleId": "n_bb6e4f89649e94a3", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_b5de9ac6a3f088eb": { "inputs": { "to": { "kind": "value", "value": "recipient@example.com" }, "subject": { "kind": "value", "value": "Weekly Search Console Report" }, "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_37531295eefd9dc5", "output": "text" } ] }, "isHtml": { "kind": "value", "value": false } }, "name": "Email the report", "kind": "task", "task": { "inputs": [ { "description": "Primary recipient email address.", "jsonSchema": { "type": "string", "description": "Primary recipient email address." }, "nullable": true, "handle": "to", "value": null }, { "description": "Additional To recipients.", "jsonSchema": { "type": "array", "items": { "type": "string", "description": "An array item." }, "description": "Additional To recipients." }, "nullable": true, "handle": "extraRecipients", "value": null }, { "description": "Cc recipients.", "jsonSchema": { "anyOf": [ { "type": "string", "description": "A union variant." }, { "type": "array", "items": { "type": "string", "description": "An array item." }, "description": "A union variant." } ], "description": "Cc recipients." }, "nullable": true, "handle": "cc", "value": null }, { "description": "Bcc recipients.", "jsonSchema": { "anyOf": [ { "type": "string", "description": "A union variant." }, { "type": "array", "items": { "type": "string", "description": "An array item." }, "description": "A union variant." } ], "description": "Bcc recipients." }, "nullable": true, "handle": "bcc", "value": null }, { "description": "Email subject line.", "jsonSchema": { "type": "string", "description": "Email subject line." }, "nullable": true, "handle": "subject", "value": null }, { "description": "Email body content.", "jsonSchema": { "type": "string", "description": "Email body content." }, "nullable": true, "handle": "body", "value": null }, { "description": "Set to true when the body content is already HTML.", "jsonSchema": { "type": "boolean", "description": "Set to true when the body content is already HTML." }, "nullable": true, "handle": "isHtml", "value": null }, { "description": "Attachments and CID inline images. Up to 25,000,000 decoded bytes in total and 35,000,000 MIME bytes.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "filename": { "type": "string", "description": "Attachment filename; omit for an unnamed attachment." }, "mimeType": { "type": "string", "description": "MIME type without parameters; defaults to application/octet-stream." }, "contentBase64": { "type": "string", "description": "Standard padded Base64 content. Empty string represents a zero-byte file. Supply this or fileUrl." }, "fileUrl": { "type": "string", "format": "uri", "description": "Public URL to download the attachment. Supply this or contentBase64." }, "contentId": { "type": "string", "minLength": 1, "description": "Bare Content-ID without cid: or angle brackets; reference it as cid: in HTML." }, "disposition": { "type": "string", "enum": [ "inline", "attachment" ], "description": "Defaults to inline when contentId is set, otherwise attachment. Inline requires contentId." } }, "additionalProperties": false, "description": "An attachment or CID inline resource.", "oneOf": [ { "required": [ "contentBase64" ] }, { "required": [ "fileUrl" ] } ] }, "maxItems": 100, "description": "Attachments and CID inline images. Up to 25,000,000 decoded bytes in total and 35,000,000 MIME bytes." }, "nullable": true, "handle": "attachments", "value": null }, { "description": "Verified Gmail send-as alias to use in the From header.", "jsonSchema": { "type": "string", "description": "Verified Gmail send-as alias to use in the From header." }, "nullable": true, "handle": "fromEmail", "value": null } ], "outputs": [ { "description": "Gmail message ID.", "jsonSchema": { "type": "string", "description": "Gmail message ID." }, "nullable": false, "handle": "messageId" }, { "description": "Gmail thread ID.", "jsonSchema": { "type": "string", "description": "Gmail thread ID." }, "nullable": true, "handle": "threadId" } ], "name": "Email the report", "executor": { "kind": "connector", "action": "gmail.send_email" } } } }, "edges": [ { "source": "n_d98c8474e0ed9efb", "target": "n_cbf9b8ae62f5dbdc" }, { "source": "n_cbf9b8ae62f5dbdc", "target": "n_9e217dc6d424a2ce" }, { "source": "n_9e217dc6d424a2ce", "target": "n_37531295eefd9dc5" }, { "source": "n_37531295eefd9dc5", "target": "n_b5de9ac6a3f088eb" } ] } }, "modules": { "n_697d89b75025a109": { "name": "Set the reporting dates", "imports": [], "source": "export default function window(){const p=new Intl.DateTimeFormat('en-CA-u-ca-iso8601',{timeZone:'America/Los_Angeles',year:'numeric',month:'2-digit',day:'2-digit'}).formatToParts(new Date()),v=Object.fromEntries(p.map(x=>[x.type,x.value])),today=Date.UTC(Number(v.year),Number(v.month)-1,Number(v.day)),date=n=>new Date(today-n*86400000).toISOString().slice(0,10);return {startDate:date(7),endDate:date(1)};}\n" }, "n_bb6e4f89649e94a3": { "name": "Prepare the report", "imports": [], "source": "export default function summarize({rows,startDate,endDate}){if(!Array.isArray(rows)||rows.length>10)throw Error('Invalid Search Console rows');let lines=[];for(const [i,r] of rows.entries()){if(!Array.isArray(r.keys)||r.keys.length!==1||typeof r.keys[0]!=='string'||!['clicks','impressions','ctr','position'].every(k=>typeof r[k]==='number'&&Number.isFinite(r[k])))throw Error('Invalid Search Console row');const query=r.keys[0].replace(/[\\r\\n]+/g,' ');lines.push(`${i+1}. ${query} - Clicks: ${r.clicks}, Impressions: ${r.impressions}, CTR: ${r.ctr.toFixed(2)}, Position: ${r.position.toFixed(2)}`)}return {text:`Top 10 Search Queries (${startDate} through ${endDate}, Pacific Time):\\n\\n${lines.length?lines.join('\\n'):'No data returned.'}`};}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }