diff --git a/packages/nodes-base/nodes/Google/Analytics/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Analytics/GenericFunctions.ts index 14f4905d26..7c5628483c 100644 --- a/packages/nodes-base/nodes/Google/Analytics/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Analytics/GenericFunctions.ts @@ -27,11 +27,13 @@ export async function googleApiRequest(this: IExecuteFunctions | IExecuteSingleF }; options = Object.assign({}, options, option); - try { if (Object.keys(body).length === 0) { delete options.body; } + if (Object.keys(qs).length === 0) { + delete options.qs; + } //@ts-ignore return await this.helpers.requestOAuth2.call(this, 'googleAnalyticsOAuth2', options); @@ -45,12 +47,11 @@ export async function googleApiRequestAllItems(this: IExecuteFunctions | ILoadOp const returnData: IDataObject[] = []; let responseData; - body.pageSize = 100; do { responseData = await googleApiRequest.call(this, method, endpoint, body, query, uri); if (body.reportRequests && Array.isArray(body.reportRequests)) { - body.reportRequests[0].pageToken = responseData['nextPageToken']; + body.reportRequests[0]['pageToken'] = responseData[propertyName][0].nextPageToken; } else { body.pageToken = responseData['nextPageToken']; } @@ -58,28 +59,42 @@ export async function googleApiRequestAllItems(this: IExecuteFunctions | ILoadOp } while ( (responseData['nextPageToken'] !== undefined && responseData['nextPageToken'] !== '') || - (responseData['reports'] && - responseData['reports'][0].nextPageToken && - responseData['reports'][0].nextPageToken !== undefined) + (responseData[propertyName] && + responseData[propertyName][0].nextPageToken && + responseData[propertyName][0].nextPageToken !== undefined) ); return returnData; } -export function simplify(responseData: any) { // tslint:disable-line:no-any - const { columnHeader: { dimensions }, data: { rows } } = responseData[0]; - responseData = []; - for (const row of rows) { - const data: IDataObject = {}; - if (dimensions) { - for (let i = 0; i < dimensions.length; i++) { - data[dimensions[i]] = row.dimensions[i]; +export function simplify(responseData: any | [any]) { // tslint:disable-line:no-any + const response = []; + for (const { columnHeader: { dimensions }, data: { rows } } of responseData) { + for (const row of rows) { + const data: IDataObject = {}; + if (dimensions) { + for (let i = 0; i < dimensions.length; i++) { + data[dimensions[i]] = row.dimensions[i]; + data['total'] = row.metrics[0].values.join(','); + } + } else { data['total'] = row.metrics[0].values.join(','); } - } else { - data['total'] = row.metrics[0].values.join(','); + response.push(data); } - responseData.push(data); } - return responseData; + return response; +} + +export function merge(responseData: [any]) { // tslint:disable-line:no-any + const response: { columnHeader: IDataObject, data: { rows: [] } } = { + columnHeader: responseData[0].columnHeader, + data: responseData[0].data, + }; + const allRows = []; + for (const { data: { rows } } of responseData) { + allRows.push(...rows); + } + response.data.rows = allRows as []; + return [response]; } diff --git a/packages/nodes-base/nodes/Google/Analytics/GoogleAnalytics.node.ts b/packages/nodes-base/nodes/Google/Analytics/GoogleAnalytics.node.ts index 54ef98af43..84081b766d 100644 --- a/packages/nodes-base/nodes/Google/Analytics/GoogleAnalytics.node.ts +++ b/packages/nodes-base/nodes/Google/Analytics/GoogleAnalytics.node.ts @@ -24,13 +24,14 @@ import { import { googleApiRequest, googleApiRequestAllItems, + merge, simplify, } from './GenericFunctions'; import * as moment from 'moment-timezone'; import { - IData + IData, } from './Interfaces'; export class GoogleAnalytics implements INodeType { @@ -69,7 +70,7 @@ export class GoogleAnalytics implements INodeType { value: 'userActivity', }, ], - default:'report', + default: 'report', }, //------------------------------- // Reports Operations @@ -152,12 +153,13 @@ export class GoogleAnalytics implements INodeType { let endpoint = ''; let responseData; for (let i = 0; i < items.length; i++) { - if(resource === 'report') { - if(operation === 'get') { + if (resource === 'report') { + if (operation === 'get') { //https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/reports/batchGet method = 'POST'; endpoint = '/v4/reports:batchGet'; const viewId = this.getNodeParameter('viewId', i) as string; + const returnAll = this.getNodeParameter('returnAll', 0) as boolean; const additionalFields = this.getNodeParameter( 'additionalFields', i, @@ -165,63 +167,69 @@ export class GoogleAnalytics implements INodeType { const simple = this.getNodeParameter('simple', i) as boolean; const body: IData = { - viewId, + viewId, }; - if(additionalFields.useResourceQuotas){ + if (additionalFields.useResourceQuotas) { qs.useResourceQuotas = additionalFields.useResourceQuotas; } - if(additionalFields.dateRangesUi){ + if (additionalFields.dateRangesUi) { const dateValues = (additionalFields.dateRangesUi as IDataObject).dateRanges as IDataObject; - if(dateValues){ + if (dateValues) { const start = dateValues.startDate as string; const end = dateValues.endDate as string; Object.assign( body, { dateRanges: - [ - { - startDate: moment(start).utc().format('YYYY-MM-DD'), - endDate: moment(end).utc().format('YYYY-MM-DD'), - }, - ], + [ + { + startDate: moment(start).utc().format('YYYY-MM-DD'), + endDate: moment(end).utc().format('YYYY-MM-DD'), + }, + ], }, ); } } - if(additionalFields.metricsUi) { + if (additionalFields.metricsUi) { const metrics = (additionalFields.metricsUi as IDataObject).metricValues as IDataObject[]; body.metrics = metrics; } - if(additionalFields.dimensionUi){ + if (additionalFields.dimensionUi) { const dimensions = (additionalFields.dimensionUi as IDataObject).dimensionValues as IDataObject[]; if (dimensions) { body.dimensions = dimensions; } } - if(additionalFields.includeEmptyRows){ + if (additionalFields.includeEmptyRows) { Object.assign(body, { includeEmptyRows: additionalFields.includeEmptyRows }); } - if(additionalFields.hideTotals){ + if (additionalFields.hideTotals) { Object.assign(body, { hideTotals: additionalFields.hideTotals }); } - if(additionalFields.hideValueRanges){ + if (additionalFields.hideValueRanges) { Object.assign(body, { hideTotals: additionalFields.hideTotals }); } - responseData = await googleApiRequest.call(this, method, endpoint, { reportRequests: [body] }, qs); - responseData = responseData.reports; + if (returnAll === true) { + responseData = await googleApiRequestAllItems.call(this, 'reports', method, endpoint, { reportRequests: [body] }, qs); + } else { + responseData = await googleApiRequest.call(this, method, endpoint, { reportRequests: [body] }, qs); + responseData = responseData.reports; + } if (simple === true) { responseData = simplify(responseData); + } else if (returnAll === true && responseData.length > 1) { + responseData = merge(responseData); } } } - if(resource === 'userActivity') { - if(operation === 'search') { - // https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/userActivity/search + if (resource === 'userActivity') { + if (operation === 'search') { + //https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/userActivity/search method = 'POST'; endpoint = '/v4/userActivity:search'; const viewId = this.getNodeParameter('viewId', i); @@ -237,7 +245,7 @@ export class GoogleAnalytics implements INodeType { userId, }, }; - if(additionalFields.activityTypes) { + if (additionalFields.activityTypes) { Object.assign(body, { activityTypes: additionalFields.activityTypes }); } diff --git a/packages/nodes-base/nodes/Google/Analytics/ReportDescription.ts b/packages/nodes-base/nodes/Google/Analytics/ReportDescription.ts index 2428b67b4a..962ca6b3f6 100644 --- a/packages/nodes-base/nodes/Google/Analytics/ReportDescription.ts +++ b/packages/nodes-base/nodes/Google/Analytics/ReportDescription.ts @@ -49,6 +49,47 @@ export const reportFields = [ placeholder: '123456', description: 'The View ID of Google Analytics', }, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + operation: [ + 'get', + ], + resource: [ + 'report', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + operation: [ + 'get', + ], + resource: [ + 'report', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 1000, + }, + default: 1000, + description: 'How many results to return.', + }, { displayName: 'Simple', name: 'simple',