Skip to content

Instantly share code, notes, and snippets.

@gagan0123
Created June 19, 2023 13:40
Show Gist options
  • Select an option

  • Save gagan0123/67afee495c292b92ea978040c8c43e98 to your computer and use it in GitHub Desktop.

Select an option

Save gagan0123/67afee495c292b92ea978040c8c43e98 to your computer and use it in GitHub Desktop.
Sitemap PageSpeed Analyzer
// Importing required libraries and modules
const axios = require('axios');
const xml2js = require('xml2js');
const psi = require('psi');
const fs = require('fs');
const path = require('path');
const fastcsv = require('fast-csv');
/**
* Fetch and parse the sitemap located at the given URL.
* If it's a sitemap index, recursively fetch and parse nested sitemaps.
* @param {string} sitemapUrl - The URL of the sitemap to parse.
* @returns {Promise<Array<string>>} - An array of URLs parsed from the sitemap.
*/
const parseSitemap = async (sitemapUrl) => {
try {
// Fetching the sitemap from the given URL
const response = await axios.get(sitemapUrl);
// Parsing the XML sitemap
const parser = new xml2js.Parser();
const parsedXml = await parser.parseStringPromise(response.data);
// Handling sitemap index files by recursively parsing nested sitemaps
if (parsedXml?.sitemapindex?.sitemap) {
let urls = [];
for (const sitemap of parsedXml.sitemapindex.sitemap) {
if (sitemap.loc) {
const nestedUrls = await parseSitemap(sitemap.loc[0]);
urls = urls.concat(nestedUrls);
}
}
return urls;
}
// Handling single sitemaps and extracting URLs
if (parsedXml?.urlset?.url) {
return parsedXml.urlset.url
.slice(0, 10)
.map(url => url.loc && url.loc[0])
.filter(Boolean);
}
return [];
} catch (error) {
console.error('Error parsing sitemap:', error);
return [];
}
};
/**
* Analyze the page speed insights of a given URL for the specified strategy.
* @param {string} url - The URL to analyze.
* @param {string} strategy - The strategy to use ('mobile' or 'desktop').
* @returns {Promise<Object>} - The page speed insights data.
*/
const analyzePageSpeed = async (url, strategy) => {
try {
// Fetching PageSpeed Insights for the given URL
const result = await psi(url, {nokey: 'true', strategy});
const fieldData = result.data.loadingExperience.metrics;
const labData = result.data.lighthouseResult.audits;
// Extracting and returning relevant page speed insights data
return {
url,
strategy,
lcp_field: fieldData?.LARGEST_CONTENTFUL_PAINT_MS?.percentile || '',
cls_field: fieldData?.CUMULATIVE_LAYOUT_SHIFT_SCORE?.percentile || '',
fcp_field: fieldData?.FIRST_CONTENTFUL_PAINT_MS?.percentile || '',
ttfb_field: fieldData?.EXPERIMENTAL_TIME_TO_FIRST_BYTE?.percentile || '',
lcp_lab: labData?.['largest-contentful-paint']?.numericValue || '',
cls_lab: labData?.['cumulative-layout-shift']?.numericValue || '',
fcp_lab: labData?.['first-contentful-paint']?.numericValue || '',
speed_index_lab: labData?.['speed-index']?.numericValue || '',
tbt_lab: labData?.['total-blocking-time']?.numericValue || ''
};
} catch (error) {
console.error('Error fetching PageSpeed Insights:', error);
return {url, strategy, error: error.message};
}
};
/**
* Main function to run the sitemap parsing and page speed analysis.
*/
const run = async () => {
// Get sitemap URL and output file name from command line arguments
const [sitemapUrl, outputFileName] = process.argv.slice(2);
// Validation
if (!sitemapUrl || !outputFileName) {
console.error('Please provide a sitemap URL and an output file name as command line arguments.');
return;
}
// Fetch and parse URLs from the sitemap
const urls = await parseSitemap(sitemapUrl);
// Create CSV stream to write results
const csvStream = fastcsv.format({headers: true});
const writableStream = fs.createWriteStream(path.join(__dirname, outputFileName));
csvStream.pipe(writableStream);
// Loop through URLs and analyze page speed insights for desktop and mobile
for (const url of urls) {
console.log(`Analyzing ${url} for desktop`);
const desktopResult = await analyzePageSpeed(url, 'desktop');
csvStream.write(desktopResult);
console.log(`Analyzing ${url} for mobile`);
const mobileResult = await analyzePageSpeed(url, 'mobile');
csvStream.write(mobileResult);
}
// End the CSV stream
csvStream.end();
console.log(`Analysis complete. Results written to ${outputFileName}`);
};
// Running the main function
run();
// Run it using command line:
// node sitemapPageSpeedAnalyzer.js https://www.example.com/sitemap.xml output.csv
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment