UNPKG

n8n-nodes-google-pagespeed

Version:

n8n community node for Google PageSpeed Insights API with comprehensive performance, accessibility, and SEO analysis

388 lines 17.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GooglePageSpeed = void 0; const n8n_workflow_1 = require("n8n-workflow"); const config_1 = require("./config"); const apiUtils_1 = require("./utils/apiUtils"); const analyzeSingleUrl_1 = require("./operations/analyzeSingleUrl"); const analyzeMultipleUrls_1 = require("./operations/analyzeMultipleUrls"); const analyzeSitemap_1 = require("./operations/analyzeSitemap"); const compareUrls_1 = require("./operations/compareUrls"); class GooglePageSpeed { constructor() { this.description = { displayName: 'Google PageSpeed Insights', name: 'googlePageSpeed', icon: 'file:google-pagespeed.svg', group: ['transform'], // Fixed: Changed from 'analyze' to valid group version: 2, subtitle: '={{$parameter["operation"] + ": " + ($parameter["url"] || $parameter["urls"] || $parameter["sitemapUrl"] || "URLs")}}', description: 'Analyze website performance, accessibility, and SEO using Google PageSpeed Insights API', defaults: { name: 'Google PageSpeed', }, inputs: ['main'], // Fixed: Use string instead of NodeConnectionType outputs: ['main'], // Fixed: Use string instead of NodeConnectionType credentials: [ { name: 'googlePageSpeedApi', required: true, }, ], properties: [ { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, options: [ { name: 'Analyze Single URL', value: 'analyzeSingle', description: 'Analyze a single website URL', action: 'Analyze a single website URL', }, { name: 'Analyze Multiple URLs', value: 'analyzeMultiple', description: 'Analyze multiple website URLs in batch', action: 'Analyze multiple website URLs in batch', }, { name: 'Analyze Sitemap', value: 'analyzeSitemap', description: 'Automatically analyze all URLs from a website sitemap', action: 'Analyze all URLs from a website sitemap', }, { name: 'Compare URLs', value: 'compareUrls', description: 'Compare performance between different URLs or time periods', action: 'Compare performance between URLs', }, ], default: 'analyzeSingle', }, // Single URL Analysis { displayName: 'URL', name: 'url', type: 'string', required: true, default: '', placeholder: 'example.com or https://example.com', description: 'The URL of the website to analyze. Protocol (https://) will be added automatically if missing.', displayOptions: { show: { operation: ['analyzeSingle'], }, }, }, // Multiple URLs Analysis { displayName: 'URLs', name: 'urls', type: 'string', typeOptions: { multipleValues: true, }, required: true, default: [], placeholder: 'https://example.com', description: 'Multiple URLs to analyze. Each URL will be processed separately.', displayOptions: { show: { operation: ['analyzeMultiple'], }, }, }, // Sitemap Analysis { displayName: 'Sitemap URL', name: 'sitemapUrl', type: 'string', required: true, default: '', placeholder: 'https://example.com/sitemap.xml', description: 'URL of the XML sitemap to analyze. All URLs in the sitemap will be extracted and analyzed.', displayOptions: { show: { operation: ['analyzeSitemap'], }, }, }, { displayName: 'URL Filters', name: 'urlFilters', type: 'collection', placeholder: 'Add Filter', default: {}, description: 'Optional filters to limit which URLs from the sitemap are analyzed', displayOptions: { show: { operation: ['analyzeSitemap'], }, }, options: [ { displayName: 'Include Pattern', name: 'includePattern', type: 'string', default: '', placeholder: '/blog/, /products/', description: 'Only analyze URLs containing these patterns (comma-separated)', }, { displayName: 'Exclude Pattern', name: 'excludePattern', type: 'string', default: '', placeholder: '/admin/, /api/', description: 'Skip URLs containing these patterns (comma-separated)', }, { displayName: 'Max URLs', name: 'maxUrls', type: 'number', default: 50, description: 'Maximum number of URLs to analyze (to avoid quota issues)', }, { displayName: 'URL Type', name: 'urlType', type: 'options', options: [ { name: 'All URLs', value: 'all' }, { name: 'Pages Only', value: 'pages' }, { name: 'Posts Only', value: 'posts' }, ], default: 'all', description: 'Type of URLs to analyze based on URL patterns', }, ], }, // Compare URLs Operation { displayName: 'Comparison Type', name: 'compareOperation', type: 'options', options: [ { name: 'Compare Two URLs', value: 'compareTwo', description: 'Compare performance between two different URLs', }, { name: 'Before/After Analysis', value: 'beforeAfter', description: 'Compare current analysis with previous baseline', }, { name: 'Batch Comparison', value: 'batch', description: 'Compare multiple URLs from input data', }, ], default: 'compareTwo', displayOptions: { show: { operation: ['compareUrls'], }, }, }, { displayName: 'First URL', name: 'url1', type: 'string', required: true, default: '', placeholder: 'https://example.com', description: 'First URL to compare', displayOptions: { show: { operation: ['compareUrls'], compareOperation: ['compareTwo'], }, }, }, { displayName: 'Second URL', name: 'url2', type: 'string', required: true, default: '', placeholder: 'https://example.com/page2', description: 'Second URL to compare', displayOptions: { show: { operation: ['compareUrls'], compareOperation: ['compareTwo'], }, }, }, { displayName: 'URL', name: 'url', type: 'string', required: true, default: '', placeholder: 'https://example.com', description: 'URL to analyze and compare with baseline', displayOptions: { show: { operation: ['compareUrls'], compareOperation: ['beforeAfter'], }, }, }, { displayName: 'Baseline Data', name: 'baselineData', type: 'json', default: '', description: 'Previous analysis data to use as baseline (optional - will use input data if not provided)', displayOptions: { show: { operation: ['compareUrls'], compareOperation: ['beforeAfter'], }, }, }, // Common Settings { displayName: 'Strategy', name: 'strategy', type: 'options', options: [...config_1.STRATEGY_OPTIONS], // Fixed: Spread to make mutable default: 'mobile', description: 'The analysis strategy to use. Mobile-first is recommended for modern web development.', }, { displayName: 'Categories', name: 'categories', type: 'multiOptions', options: [...config_1.CATEGORY_OPTIONS], // Fixed: Spread to make mutable default: ['performance', 'accessibility', 'best-practices', 'seo'], description: 'Categories to analyze. All categories are recommended for comprehensive analysis.', }, { displayName: 'Additional Options', name: 'additionalFields', type: 'collection', placeholder: 'Add Option', default: {}, options: [ { displayName: 'Locale', name: 'locale', type: 'options', options: [...config_1.SUPPORTED_LOCALES], // Fixed: Spread to make mutable default: 'en', description: 'The locale used to localize formatted results', }, { displayName: 'Include Screenshot', name: 'screenshot', type: 'boolean', default: false, description: 'Whether to include a screenshot of the analyzed page in results', }, { displayName: 'Output Format', name: 'outputFormat', type: 'options', options: [...config_1.OUTPUT_FORMAT_OPTIONS], // Fixed: Spread to make mutable default: 'complete', description: 'How much data to return in the response', }, { displayName: 'Skip Content Validation', name: 'skipContentValidation', type: 'boolean', default: false, description: 'Skip checking if URLs return HTML content (may result in errors for XML/API endpoints)', }, { displayName: 'Retry Attempts', name: 'retryAttempts', type: 'number', default: 2, description: 'Number of retry attempts for failed requests', typeOptions: { minValue: 0, maxValue: 5, }, }, { displayName: 'Custom Timeout (seconds)', name: 'customTimeout', type: 'number', default: 60, description: 'Custom timeout for API requests in seconds', typeOptions: { minValue: 10, maxValue: 300, }, }, ], }, ], }; } async execute() { const operation = this.getNodeParameter('operation', 0); const credentials = (await this.getCredentials('googlePageSpeedApi')); if (!credentials.apiKey) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No API key found in credentials. Please configure your Google PageSpeed API credentials.'); } const apiKey = credentials.apiKey; // Validate API key (optional but recommended) const isValidKey = await (0, apiUtils_1.validateApiKey)(this, apiKey); if (!isValidKey) { console.warn('API key validation failed, but continuing with execution...'); } let results = []; try { switch (operation) { case 'analyzeSingle': results = await (0, analyzeSingleUrl_1.executeAnalyzeSingle)(this, apiKey); break; case 'analyzeMultiple': results = await (0, analyzeMultipleUrls_1.executeAnalyzeMultiple)(this, apiKey); break; case 'analyzeSitemap': results = await (0, analyzeSitemap_1.executeAnalyzeSitemap)(this, apiKey); break; case 'compareUrls': results = await (0, compareUrls_1.executeCompareUrls)(this, apiKey); break; default: throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`); } // Add execution metadata to all results results.forEach(result => { if (result.json && typeof result.json === 'object') { result.json.executionMetadata = { nodeVersion: 2, executionTime: new Date().toISOString(), operation, totalResults: results.length, }; } }); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; // Enhanced error logging console.error('PageSpeed Insights execution failed:', { operation, error: errorMessage, timestamp: new Date().toISOString(), }); throw new n8n_workflow_1.NodeOperationError(this.getNode(), `PageSpeed Insights analysis failed: ${errorMessage}. Please check your API key, URL format, and network connection.`); } return [results]; } } exports.GooglePageSpeed = GooglePageSpeed; //# sourceMappingURL=GooglePageSpeed.node.js.map