n8n-nodes-google-search-console
Version:
n8n node for Google Search Console API integration
625 lines (624 loc) • 32.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GoogleSearchConsole = void 0;
const n8n_workflow_1 = require("n8n-workflow");
function toGscDate(d) {
if (!d)
return '';
const dt = new Date(d);
if (Number.isNaN(dt.getTime()))
return '';
return dt.toISOString().split('T')[0];
}
function defaultedRange(start, end) {
const endDt = end ? new Date(end) : new Date();
const startDt = start ? new Date(start) : new Date(endDt.getTime() - 28 * 86400000);
return { startDate: toGscDate(start !== null && start !== void 0 ? start : startDt.toISOString()), endDate: toGscDate(end !== null && end !== void 0 ? end : endDt.toISOString()) };
}
function rangeFromPreset(mode, customStart, customEnd) {
const end = customEnd ? new Date(customEnd) : new Date();
let start = customStart ? new Date(customStart) : new Date(end);
if (mode !== 'custom') {
const e = new Date(end);
const s = new Date(end);
switch (mode) {
case 'last7d':
s.setDate(e.getDate() - 7);
break;
case 'last28d':
s.setDate(e.getDate() - 28);
break;
case 'last3mo':
s.setMonth(e.getMonth() - 3);
break;
case 'last12mo':
s.setMonth(e.getMonth() - 12);
break;
default: s.setDate(e.getDate() - 28);
}
return { startDate: toGscDate(s.toISOString()), endDate: toGscDate(e.toISOString()) };
}
return defaultedRange(customStart, customEnd);
}
function mapRow(dimensions, row) {
const obj = {};
if (Array.isArray(row.keys)) {
dimensions.forEach((d, idx) => { obj[d] = row.keys[idx]; });
}
obj.clicks = row.clicks;
obj.impressions = row.impressions;
obj.ctr = row.ctr;
obj.position = row.position;
return obj;
}
async function fetchAllRows(ctx, siteUrl, body, targetLimit) {
var _a;
const rows = [];
let startRow = 0;
const perRequest = Math.max(100, Math.min((_a = body.rowLimit) !== null && _a !== void 0 ? _a : 1000, 25000));
while (rows.length < targetLimit) {
const resp = await ctx.helpers.httpRequestWithAuthentication.call(ctx, 'GoogleSearchConsoleOAuth2Api', {
method: 'POST',
url: `https://www.googleapis.com/webmasters/v3/sites/${encodeURIComponent(siteUrl)}/searchAnalytics/query`,
body: { ...body, rowLimit: perRequest, startRow },
});
const chunk = Array.isArray(resp === null || resp === void 0 ? void 0 : resp.rows) ? resp.rows : [];
if (chunk.length === 0)
break;
rows.push(...chunk);
startRow += chunk.length;
if (chunk.length < perRequest)
break;
if (rows.length >= targetLimit)
break;
}
return rows.slice(0, targetLimit);
}
function keyFromRow(dimensions, row) {
var _a;
return ((_a = row.keys) !== null && _a !== void 0 ? _a : []).join('||');
}
function rowsToMap(rows, dims) {
const m = new Map();
for (const r of rows)
m.set(keyFromRow(dims, r), r);
return m;
}
function daysInclusive(a, b) {
const start = new Date(a);
const end = new Date(b);
const msPerDay = 24 * 60 * 60 * 1000;
const startUTC = Date.UTC(start.getFullYear(), start.getMonth(), start.getDate());
const endUTC = Date.UTC(end.getFullYear(), end.getMonth(), end.getDate());
return Math.floor((endUTC - startUTC) / msPerDay) + 1;
}
function shiftDays(iso, days) {
const d = new Date(iso);
d.setDate(d.getDate() + days);
return toGscDate(d.toISOString());
}
function shiftYears(iso, years) {
const d = new Date(iso);
d.setFullYear(d.getFullYear() + years);
return toGscDate(d.toISOString());
}
function buildCompareRanges(mode, rangeA, customB) {
if (mode === 'prevPeriod') {
const dur = daysInclusive(rangeA.startDate, rangeA.endDate);
const endB = shiftDays(rangeA.startDate, -1);
const startB = shiftDays(endB, -(dur - 1));
return { rangeA, rangeB: { startDate: startB, endDate: endB } };
}
if (mode === 'prevYear') {
const startB = shiftYears(rangeA.startDate, -1);
const endB = shiftYears(rangeA.endDate, -1);
return { rangeA, rangeB: { startDate: startB, endDate: endB } };
}
const { startDate, endDate } = rangeFromPreset((customB === null || customB === void 0 ? void 0 : customB.mode) || 'last28d', customB === null || customB === void 0 ? void 0 : customB.start, customB === null || customB === void 0 ? void 0 : customB.end);
return { rangeA, rangeB: { startDate, endDate } };
}
function validateSiteUrlOrThrow(node, itemIndex, siteUrl, context) {
const trimmed = (siteUrl || '').trim();
if (!trimmed || trimmed === '__NO_SITES__') {
throw new n8n_workflow_1.NodeOperationError(node.getNode(), `No site selected for ${context}.`, { itemIndex });
}
if (!/^https?:\/\//.test(trimmed) && !/^sc-domain:/.test(trimmed)) {
throw new n8n_workflow_1.NodeOperationError(node.getNode(), 'Site URL must start with http(s):// or sc-domain:. Example: https://example.com/ or sc-domain:example.com', { itemIndex });
}
return trimmed;
}
/* ========= Node ========= */
class GoogleSearchConsole {
constructor() {
this.description = {
displayName: 'Google Search Console',
name: 'googleSearchConsole',
icon: 'file:googlesearchconsole.svg',
group: ['resource'],
version: 1,
description: 'Connect to Google Search Console API',
usableAsTool: true,
defaults: { name: 'Search Console' },
subtitle: '={{$parameter.operation}}',
inputs: ['main'],
outputs: ['main'],
credentials: [{ name: 'GoogleSearchConsoleOAuth2Api', required: true }],
requestDefaults: {
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
},
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
options: [{ name: 'Site', value: 'site' }],
default: 'site',
required: true,
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
options: [
{ name: 'Get Sites', value: 'getSites', action: 'List verified sites' },
{ name: 'Get Page Insights', value: 'getPageInsights', action: 'Query search analytics' },
{ name: 'Inspect URL', value: 'inspectUrl', action: 'URL Inspection (index status)' },
{ name: 'Compare Page Insights', value: 'comparePageInsights', action: 'Compare search analytics between two date ranges' },
],
default: 'getSites',
required: true,
displayOptions: { show: { resource: ['site'] } },
},
/* ---------- getPageInsights ---------- */
{
displayName: 'Site URL Mode',
name: 'siteUrlMode',
type: 'options',
options: [
{ name: 'Pick from My Verified Sites', value: 'list' },
{ name: 'Enter Manually', value: 'manual' },
],
default: 'list',
displayOptions: { show: { resource: ['site'], operation: ['getPageInsights'] } },
},
{
displayName: 'Site URL',
name: 'siteUrl',
type: 'options',
typeOptions: { loadOptionsMethod: 'getVerifiedSites' },
displayOptions: {
show: { resource: ['site'], operation: ['getPageInsights'], siteUrlMode: ['list'] },
},
default: '',
required: true,
},
{
displayName: 'Site URL (Manual)',
name: 'siteUrlManual',
type: 'string',
placeholder: 'https://example.com/ or sc-domain:example.com',
hint: 'Enter a verified property URL. Supports domain properties via sc-domain:example.com',
displayOptions: {
show: { resource: ['site'], operation: ['getPageInsights'], siteUrlMode: ['manual'] },
},
default: '',
required: true,
},
{
displayName: 'Date Range',
name: 'dateRangeMode',
type: 'options',
options: [
{ name: 'Last 7 Days', value: 'last7d' },
{ name: 'Last 28 Days', value: 'last28d' },
{ name: 'Last 3 Months', value: 'last3mo' },
{ name: 'Last 12 Months', value: 'last12mo' },
{ name: 'Custom', value: 'custom' },
],
default: 'last28d',
hint: 'Select preset or Custom to set exact dates.',
displayOptions: { show: { resource: ['site'], operation: ['getPageInsights'] } },
},
{
displayName: 'Start Date',
name: 'startDate',
type: 'dateTime',
hint: 'Shown only if Date Range is Custom.',
displayOptions: { show: { resource: ['site'], operation: ['getPageInsights'], dateRangeMode: ['custom'] } },
default: '',
},
{
displayName: 'End Date',
name: 'endDate',
type: 'dateTime',
hint: 'Shown only if Date Range is Custom.',
displayOptions: { show: { resource: ['site'], operation: ['getPageInsights'], dateRangeMode: ['custom'] } },
default: '',
},
{
displayName: 'Row Limit',
name: 'rowLimit',
type: 'number',
typeOptions: { minValue: 1, maxValue: 25000 },
default: 1000,
displayOptions: { show: { resource: ['site'], operation: ['getPageInsights'] } },
},
{
displayName: 'Search Type',
name: 'searchType',
type: 'options',
options: [
{ name: 'Web', value: 'web' },
{ name: 'Image', value: 'image' },
{ name: 'Video', value: 'video' },
{ name: 'News', value: 'news' },
],
default: 'web',
displayOptions: { show: { resource: ['site'], operation: ['getPageInsights'] } },
},
{
displayName: 'Dimensions',
name: 'dimensions',
type: 'multiOptions',
options: [
{ name: 'Date', value: 'date' },
{ name: 'Page', value: 'page' },
{ name: 'Query', value: 'query' },
{ name: 'Country', value: 'country' },
{ name: 'Device', value: 'device' },
],
default: ['page'],
displayOptions: { show: { resource: ['site'], operation: ['getPageInsights'] } },
},
/* ---------- inspectUrl ---------- */
{
displayName: 'Site URL Mode',
name: 'inspectSiteUrlMode',
type: 'options',
options: [
{ name: 'Pick from My Verified Sites', value: 'list' },
{ name: 'Enter Manually', value: 'manual' },
],
default: 'list',
displayOptions: { show: { resource: ['site'], operation: ['inspectUrl'] } },
},
{
displayName: 'Site URL',
name: 'inspectSiteUrl',
type: 'options',
typeOptions: { loadOptionsMethod: 'getVerifiedSites' },
displayOptions: {
show: { resource: ['site'], operation: ['inspectUrl'], inspectSiteUrlMode: ['list'] },
},
default: '',
required: true,
},
{
displayName: 'Site URL (Manual)',
name: 'inspectSiteUrlManual',
type: 'string',
placeholder: 'https://example.com/ or sc-domain:example.com',
hint: 'Supports sc-domain:example.com for domain properties',
displayOptions: {
show: { resource: ['site'], operation: ['inspectUrl'], inspectSiteUrlMode: ['manual'] },
},
default: '',
required: true,
},
{
displayName: 'Inspection URL',
name: 'inspectionUrl',
type: 'string',
displayOptions: { show: { resource: ['site'], operation: ['inspectUrl'] } },
default: '',
required: true,
},
{
displayName: 'Language Code',
name: 'languageCode',
type: 'string',
displayOptions: { show: { resource: ['site'], operation: ['inspectUrl'] } },
default: '',
},
/* ---------- comparePageInsights ---------- */
{
displayName: 'Site URL Mode',
name: 'siteUrlModeCompare',
type: 'options',
options: [
{ name: 'Pick from My Verified Sites', value: 'list' },
{ name: 'Enter Manually', value: 'manual' },
],
default: 'list',
displayOptions: { show: { resource: ['site'], operation: ['comparePageInsights'] } },
},
{
displayName: 'Site URL',
name: 'siteUrlCompare',
type: 'options',
typeOptions: { loadOptionsMethod: 'getVerifiedSites' },
displayOptions: {
show: { resource: ['site'], operation: ['comparePageInsights'], siteUrlModeCompare: ['list'] },
},
default: '',
required: true,
},
{
displayName: 'Site URL (Manual)',
name: 'siteUrlCompareManual',
type: 'string',
placeholder: 'https://example.com/ or sc-domain:example.com',
hint: 'Enter a verified property URL (supports sc-domain:example.com)',
displayOptions: {
show: { resource: ['site'], operation: ['comparePageInsights'], siteUrlModeCompare: ['manual'] },
},
default: '',
required: true,
},
/* ---- Range A ---- */
{
displayName: 'Date Range A',
name: 'dateRangeModeA',
type: 'options',
options: [
{ name: 'Last 7 Days', value: 'last7d' },
{ name: 'Last 28 Days', value: 'last28d' },
{ name: 'Last 3 Months', value: 'last3mo' },
{ name: 'Last 12 Months', value: 'last12mo' },
{ name: 'Custom', value: 'custom' },
],
default: 'last28d',
displayOptions: { show: { resource: ['site'], operation: ['comparePageInsights'] } },
},
{
displayName: 'Start Date A',
name: 'startDateA',
type: 'dateTime',
displayOptions: { show: { resource: ['site'], operation: ['comparePageInsights'], dateRangeModeA: ['custom'] } },
default: '',
},
{
displayName: 'End Date A',
name: 'endDateA',
type: 'dateTime',
displayOptions: { show: { resource: ['site'], operation: ['comparePageInsights'], dateRangeModeA: ['custom'] } },
default: '',
},
{
displayName: 'Compare Mode',
name: 'compareMode',
type: 'options',
options: [
{ name: 'Previous Period', value: 'prevPeriod' },
{ name: 'Previous Year (YoY)', value: 'prevYear' },
{ name: 'Custom', value: 'custom' },
],
default: 'prevPeriod',
displayOptions: { show: { resource: ['site'], operation: ['comparePageInsights'] } },
},
/* ---- Range B (only when compare is custom) ---- */
{
displayName: 'Date Range B',
name: 'dateRangeModeB',
type: 'options',
options: [
{ name: 'Last 7 Days', value: 'last7d' },
{ name: 'Last 28 Days', value: 'last28d' },
{ name: 'Last 3 Months', value: 'last3mo' },
{ name: 'Last 12 Months', value: 'last12mo' },
{ name: 'Custom', value: 'custom' },
],
default: 'last28d',
displayOptions: { show: { resource: ['site'], operation: ['comparePageInsights'], compareMode: ['custom'] } },
},
{
displayName: 'Start Date B',
name: 'startDateB',
type: 'dateTime',
displayOptions: {
show: { resource: ['site'], operation: ['comparePageInsights'], compareMode: ['custom'], dateRangeModeB: ['custom'] },
},
default: '',
},
{
displayName: 'End Date B',
name: 'endDateB',
type: 'dateTime',
displayOptions: {
show: { resource: ['site'], operation: ['comparePageInsights'], compareMode: ['custom'], dateRangeModeB: ['custom'] },
},
default: '',
},
/* ---- Shared options ---- */
{
displayName: 'Row Limit (per range)',
name: 'rowLimitCompare',
type: 'number',
typeOptions: { minValue: 1, maxValue: 25000 },
default: 1000,
displayOptions: { show: { resource: ['site'], operation: ['comparePageInsights'] } },
},
{
displayName: 'Search Type',
name: 'searchTypeCompare',
type: 'options',
options: [
{ name: 'Web', value: 'web' },
{ name: 'Image', value: 'image' },
{ name: 'Video', value: 'video' },
{ name: 'News', value: 'news' },
],
default: 'web',
displayOptions: { show: { resource: ['site'], operation: ['comparePageInsights'] } },
},
{
displayName: 'Dimensions',
name: 'dimensionsCompare',
type: 'multiOptions',
options: [
{ name: 'Date', value: 'date' },
{ name: 'Page', value: 'page' },
{ name: 'Query', value: 'query' },
{ name: 'Country', value: 'country' },
{ name: 'Device', value: 'device' },
],
default: ['page'],
displayOptions: { show: { resource: ['site'], operation: ['comparePageInsights'] } },
},
],
};
this.methods = {
loadOptions: {
async getVerifiedSites() {
try {
const resp = await this.helpers.httpRequestWithAuthentication.call(this, 'GoogleSearchConsoleOAuth2Api', { method: 'GET', url: 'https://www.googleapis.com/webmasters/v3/sites' });
const sites = Array.isArray(resp === null || resp === void 0 ? void 0 : resp.siteEntry) ? resp.siteEntry : [];
if (!sites.length) {
return [{
name: 'No verified properties found — verify your site in Google Search Console first.',
value: '__NO_SITES__',
}];
}
const sorted = [...sites].sort((a, b) => {
const av = a.siteUrl.startsWith('sc-domain:') ? 0 : 1;
const bv = b.siteUrl.startsWith('sc-domain:') ? 0 : 1;
return av - bv || a.siteUrl.localeCompare(b.siteUrl);
});
return sorted.map((s) => ({
name: `${s.siteUrl}${s.permissionLevel ? ` (${s.permissionLevel})` : ''}`,
value: s.siteUrl,
description: s.permissionLevel || '',
}));
}
catch (err) {
return [{
name: `Error loading sites: ${(err === null || err === void 0 ? void 0 : err.message) || 'Failed to load sites. Check your OAuth credentials/permissions.'}`,
value: '__NO_SITES__',
}];
}
},
},
};
}
async execute() {
var _a, _b, _c, _d, _e, _f;
const items = this.getInputData();
const returnData = [];
for (let i = 0; i < items.length; i++) {
const operation = this.getNodeParameter('operation', i);
const pushOk = (json) => returnData.push({ json, pairedItem: { item: i } });
const pushErr = (e) => { var _a; if (this.continueOnFail())
pushOk({ error: (_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : e });
else
throw e; };
try {
if (operation === 'getSites') {
const resp = await this.helpers.httpRequestWithAuthentication.call(this, 'GoogleSearchConsoleOAuth2Api', { method: 'GET', url: 'https://www.googleapis.com/webmasters/v3/sites' });
const sites = Array.isArray(resp === null || resp === void 0 ? void 0 : resp.siteEntry) ? resp.siteEntry : [];
sites.forEach((s) => pushOk({ resource: 'site', operation: 'getSites', ...s }));
}
if (operation === 'getPageInsights') {
const siteUrlMode = this.getNodeParameter('siteUrlMode', i);
const siteUrlInput = siteUrlMode === 'manual'
? this.getNodeParameter('siteUrlManual', i)
: this.getNodeParameter('siteUrl', i);
const siteUrl = validateSiteUrlOrThrow(this, i, siteUrlInput, 'page insights');
const dateRangeMode = this.getNodeParameter('dateRangeMode', i);
const startDateParam = this.getNodeParameter('startDate', i, '');
const endDateParam = this.getNodeParameter('endDate', i, '');
const { startDate, endDate } = rangeFromPreset(dateRangeMode, startDateParam, endDateParam);
const rowLimit = this.getNodeParameter('rowLimit', i);
const searchType = this.getNodeParameter('searchType', i);
const dimensions = this.getNodeParameter('dimensions', i);
const body = { startDate, endDate, dimensions, rowLimit: Math.max(1, Math.min(rowLimit, 25000)), searchType };
const rows = await fetchAllRows(this, siteUrl, body, rowLimit);
rows.forEach((r) => pushOk({ resource: 'site', operation: 'getPageInsights', ...mapRow(dimensions, r) }));
}
if (operation === 'inspectUrl') {
const siteUrlMode = this.getNodeParameter('inspectSiteUrlMode', i);
const siteUrlInput = siteUrlMode === 'manual'
? this.getNodeParameter('inspectSiteUrlManual', i)
: this.getNodeParameter('inspectSiteUrl', i);
const siteUrl = validateSiteUrlOrThrow(this, i, siteUrlInput, 'URL inspection');
const inspectionUrl = this.getNodeParameter('inspectionUrl', i).trim();
if (!/^https?:\/\//.test(inspectionUrl)) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Inspection URL must start with http(s)://', { itemIndex: i });
}
const languageCode = this.getNodeParameter('languageCode', i) || '';
const resp = await this.helpers.httpRequestWithAuthentication.call(this, 'GoogleSearchConsoleOAuth2Api', {
method: 'POST',
url: 'https://searchconsole.googleapis.com/v1/urlInspection/index:inspect',
body: { inspectionUrl, siteUrl, languageCode: languageCode || undefined },
});
const result = (resp === null || resp === void 0 ? void 0 : resp.inspectionResult) || {};
pushOk({ resource: 'site', operation: 'inspectUrl', ...result });
}
/* ---------- Compare Page Insights ---------- */
if (operation === 'comparePageInsights') {
const mode = this.getNodeParameter('siteUrlModeCompare', i) || 'list';
const siteUrlInput = mode === 'manual'
? this.getNodeParameter('siteUrlCompareManual', i)
: this.getNodeParameter('siteUrlCompare', i);
const siteUrl = validateSiteUrlOrThrow(this, i, siteUrlInput, 'comparison');
const dims = this.getNodeParameter('dimensionsCompare', i) || ['page'];
if (!dims.length) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'At least one dimension is required for comparison.', { itemIndex: i });
}
// Range A (preset/custom)
const drmA = this.getNodeParameter('dateRangeModeA', i) || 'last28d';
const startA = this.getNodeParameter('startDateA', i, '') || '';
const endA = this.getNodeParameter('endDateA', i, '') || '';
const rangeA = rangeFromPreset(drmA, startA, endA);
// Compare mode: prevPeriod / prevYear / custom
const compareMode = this.getNodeParameter('compareMode', i) || 'prevPeriod';
// اگر Custom انتخاب شده، پارامترهای B را بخوان
let customB;
if (compareMode === 'custom') {
const drmB = this.getNodeParameter('dateRangeModeB', i) || 'last28d';
const startB = this.getNodeParameter('startDateB', i, '') || '';
const endB = this.getNodeParameter('endDateB', i, '') || '';
customB = { mode: drmB, start: startB, end: endB };
}
const { rangeB } = buildCompareRanges(compareMode, rangeA, customB);
const rowLimit = (this.getNodeParameter('rowLimitCompare', i) || 1000);
const searchType = this.getNodeParameter('searchTypeCompare', i) || 'web';
const baseBody = { dimensions: dims, searchType };
const rowsA = await fetchAllRows(this, siteUrl, { ...baseBody, ...rangeA, rowLimit: Math.max(1, Math.min(rowLimit, 25000)) }, rowLimit);
const rowsB = await fetchAllRows(this, siteUrl, { ...baseBody, ...rangeB, rowLimit: Math.max(1, Math.min(rowLimit, 25000)) }, rowLimit);
const mapA = rowsToMap(rowsA, dims);
const mapB = rowsToMap(rowsB, dims);
const allKeys = new Set([...mapA.keys(), ...mapB.keys()]);
for (const k of allKeys) {
const ra = mapA.get(k);
const rb = mapB.get(k);
const valsA = ra !== null && ra !== void 0 ? ra : { keys: ((_b = (_a = ra === null || ra === void 0 ? void 0 : ra.keys) !== null && _a !== void 0 ? _a : rb === null || rb === void 0 ? void 0 : rb.keys) !== null && _b !== void 0 ? _b : []), clicks: 0, impressions: 0, ctr: 0, position: 0 };
const valsB = rb !== null && rb !== void 0 ? rb : { keys: ((_d = (_c = rb === null || rb === void 0 ? void 0 : rb.keys) !== null && _c !== void 0 ? _c : ra === null || ra === void 0 ? void 0 : ra.keys) !== null && _d !== void 0 ? _d : []), clicks: 0, impressions: 0, ctr: 0, position: 0 };
const out = {};
((_f = (_e = valsA.keys) !== null && _e !== void 0 ? _e : valsB.keys) !== null && _f !== void 0 ? _f : []).forEach((v, idx) => { out[dims[idx]] = v; });
out.clicks_a = valsA.clicks;
out.clicks_b = valsB.clicks;
out.clicks_diff = valsA.clicks - valsB.clicks;
out.impr_a = valsA.impressions;
out.impr_b = valsB.impressions;
out.impr_diff = valsA.impressions - valsB.impressions;
out.ctr_a = valsA.ctr;
out.ctr_b = valsB.ctr;
out.ctr_diff = valsA.ctr - valsB.ctr;
out.pos_a = valsA.position;
out.pos_b = valsB.position;
out.pos_diff = valsA.position - valsB.position;
out.range_a = rangeA; // { startDate, endDate }
out.range_b = rangeB;
out.compare_mode = compareMode;
returnData.push({ json: { resource: 'site', operation: 'comparePageInsights', ...out }, pairedItem: { item: i } });
}
}
}
catch (error) {
pushErr(error);
}
}
return [returnData];
}
}
exports.GoogleSearchConsole = GoogleSearchConsole;