PozoAppNov266pm/scripts/generate-seo.js

234 lines
12 KiB
JavaScript

import fs from "fs";
import path from "path";
import axios from "axios";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// For production deployment, always use the production URL
// When running convert-jsx-to-html, always use production URLs for SEO
const mainDirectory = (import.meta?.env?.ENV_MAIN_BASE_URL)
|| process.env.ENV_MAIN_BASE_URL
|| 'https://www.pozo.app';
const rawApiUrl = (import.meta?.env?.ENV_API_URL) || process.env.ENV_API_URL || '';
function normalizeApiBase(url) {
if (!url) return '';
// If full http/https, use as-is
if (/^https?:\/\//i.test(url)) return url;
// If protocol-relative (//domain), prefix https:
if (/^\/\//.test(url)) return `https:${url}`;
// Otherwise, assume domain/path and prefix https://
return `https://${url}`;
}
const CommonApiUrl = normalizeApiBase(rawApiUrl).replace(/\/$/, '');
const routes = [
{ path: "index.html", pageId: 1, url: `${mainDirectory}/`},
{ path: "signin/index.html", pageId: 2, url: `${mainDirectory}/signin` },
{ path: "pricing/index.html", pageId: 3, url: `${mainDirectory}/pricing` },
{ path: "contact-us/index.html", pageId: 4, url: `${mainDirectory}/contact-us` },
{ path: "blog/index.html", pageId: 5, url: `${mainDirectory}/blog` },
{ path: "about-us/index.html", pageId: 6, url: `${mainDirectory}/about-us` },
{ path: "privacy-policy/index.html", pageId: 7, url: `${mainDirectory}/privacy-policy` },
{ path: "cookie-policy/index.html", pageId: 8, url: `${mainDirectory}/cookie-policy` },
{ path: "solutions/index.html", pageId: 9, url: `${mainDirectory}/solutions` },
{ path: "case-studies/index.html", pageId: 10, url: `${mainDirectory}/case-studies` },
{ path: "live-session/index.html", pageId: 11, url: `${mainDirectory}/live-session` },
{ path: "book-demo/index.html", pageId: 12, url: `${mainDirectory}/book-demo` },
{ path: "schedule-demo/index.html", pageId: 13, url: `${mainDirectory}/schedule-demo` },
{ path: "solutions/retail-billing/index.html", pageId: 14, url: `${mainDirectory}/solutions/retail-billing` },
{ path: "solutions/inventory-purchase/index.html", pageId: 15, url: `${mainDirectory}/solutions/inventory-purchase` },
{ path: "solutions/weighing-scale-pos/index.html", pageId: 16, url: `${mainDirectory}/solutions/weighing-scale-pos` },
{ path: "solutions/multi-store-erp/index.html", pageId: 17, url: `${mainDirectory}/solutions/multi-store-erp` },
{ path: "solutions/gst-billing-e-invoice/index.html", pageId: 18, url: `${mainDirectory}/solutions/gst-billing-e-invoice` },
{ path: "solutions/offline-billing/index.html", pageId: 19, url: `${mainDirectory}/solutions/offline-billing` },
{ path: "solutions/healthcare-management/index.html", pageId: 20, url: `${mainDirectory}/solutions/healthcare-management` },
];
const fallbackData = {
1: {
title: "Retail ERP & POS for Indian MSMEs | POZO",
description: "Fast billing, smart inventory, GST-ready POS. POZO helps kirana, mini-supermarkets & retail chains speed checkout, connect weighing scales, and manage multi-store ops.",
image: `${mainDirectory}/og/home.jpg`,
},
2: {
title: "Sign In to PozoApp | Retail ERP & POS Login",
description: "Access your business dashboard. Sign in to POZO retail ERP & POS system for billing, inventory management, and business analytics.",
image: `${mainDirectory}/og/Signin-og.jpg`,
},
3: {
title: "Pricing - Retail ERP & POS Plans | POZO",
description: "Simple plans for MSMEs. Fast billing, inventory, GST e-invoice, weighing-scale integration, WhatsApp e-bills & multi-store controls. Book a demo.",
image: `${mainDirectory}/og/pricing-og.jpg`,
},
4: {
title: "Contact POZO | Retail ERP & POS Support",
description: "Get support and sales information for POZO retail ERP & POS solutions. Contact us for billing software, inventory management, and business automation.",
image: `${mainDirectory}/og/contact-og.jpg`,
},
5: {
title: "POZO Blog — Retail ERP, POS & Grocery Billing Guides",
description: "Practical guides on POS billing, weighing-scale integration, GST e-invoices, multi-store ERP & inventory control for Indian retailers.",
image: `${mainDirectory}/og/blog-og.jpg`,
},
6: {
title: "About POZO | Retail ERP & POS Solutions for MSMEs",
description: "Learn about POZO's mission to digitize Indian retail businesses with affordable ERP & POS solutions, billing software, and inventory management.",
image: `${mainDirectory}/og/about-og.jpg`,
},
7: {
title: "Privacy Policy | POZO Retail ERP & POS",
description: "POZO's privacy policy for retail ERP & POS users. Learn how we protect your business data, billing information, and customer details.",
image: `${mainDirectory}/og/privacy-og.jpg`,
},
8: {
title: "Cookie Policy | POZO Retail ERP & POS",
description: "POZO's cookie policy explaining how we use cookies to improve your retail ERP & POS experience and website functionality.",
image: `${mainDirectory}/og/cookie-og.jpg`,
},
9: {
title: "Retail Solutions | ERP & POS Software for Every Business",
description: "Comprehensive retail solutions: billing software, inventory management, GST compliance, weighing scale integration, and multi-store ERP for Indian businesses.",
image: `${mainDirectory}/og/solutions-og.jpg`,
},
10: {
title: "Case Studies | POZO Retail ERP & POS Success Stories",
description: "Real success stories of Indian retailers using POZO ERP & POS. See how businesses improved billing speed, inventory control, and customer satisfaction.",
image: `${mainDirectory}/og/case-studies-og.jpg`,
},
11: {
title: "Live Demo Session | POZO Retail ERP & POS",
description: "Join free live demo sessions of POZO retail ERP & POS. See billing, inventory management, GST features, and weighing scale integration in action.",
image: `${mainDirectory}/og/live-session-og.jpg`,
},
12: {
title: "Book Demo | POZO Retail ERP & POS Free Trial",
description: "Book a free demo of POZO retail ERP & POS. Experience fast billing, smart inventory, GST compliance, and business automation for your store.",
image: `${mainDirectory}/og/book-demo-og.jpg`,
},
13: {
title: "Schedule Demo | POZO Retail ERP & POS Consultation",
description: "Schedule a personalized demo consultation for POZO retail ERP & POS. Get expert guidance on billing, inventory, and business digitization.",
image: `${mainDirectory}/og/schedule-demo-og.jpg`,
},
14: {
title: "Retail Billing Software | Fast POS for Kirana & Supermarkets",
description: "Lightning-fast retail billing software with barcode scanning, GST compliance, customer management, and real-time inventory updates for Indian retailers.",
image: `${mainDirectory}/og/retail-billing-og.jpg`,
},
15: {
title: "Inventory & Purchase Management | Smart Stock Control",
description: "Advanced inventory management with purchase orders, supplier management, stock alerts, expiry tracking, and automated reordering for retail businesses.",
image: `${mainDirectory}/og/inventory-purchase-og.jpg`,
},
16: {
title: "Weighing Scale POS | Integrated Billing for Grocery Stores",
description: "POS system with weighing scale integration for grocery stores, fruit vendors, and bulk retailers. Accurate billing with weight-based pricing.",
image: `${mainDirectory}/og/weighing-scale-pos-og.jpg`,
},
17: {
title: "Multi-Store ERP | Centralized Retail Chain Management",
description: "Manage multiple retail locations with centralized inventory, unified reporting, inter-store transfers, and consolidated business analytics.",
image: `${mainDirectory}/og/multi-store-erp-og.jpg`,
},
18: {
title: "GST Billing & E-Invoice | Compliant Retail Software",
description: "GST-compliant billing with automatic e-invoice generation, GSTR filing support, tax calculations, and government portal integration.",
image: `${mainDirectory}/og/gst-billing-og.jpg`,
},
19: {
title: "Offline Billing Software | Works Without Internet",
description: "Reliable offline billing software that works without internet. Automatic sync when online, ensuring uninterrupted business operations.",
image: `${mainDirectory}/og/offline-billing-og.jpg`,
},
20: {
title: "Healthcare Management System | Medical Store & Clinic ERP",
description: "Specialized ERP for medical stores, clinics, and healthcare providers with medicine inventory, prescription management, and patient records.",
image: `${mainDirectory}/og/healthcare-og.jpg`,
},
};
async function fetchSEO(pageId) {
try {
const response = await axios.get(
`${CommonApiUrl}/Seo`,
{ params: { pageId } }
);
if (response.data?.statusCode === 1 && response.data?.data?.length > 0) {
return response.data.data[0];
}
} catch (error) {
console.log(`Using fallback for PageId ${pageId}`);
}
return null;
}
async function generateSEOFiles() {
for (const route of routes) {
const dbData = await fetchSEO(route.pageId);
const fallback = fallbackData[route.pageId];
const seoData = {
title: dbData?.MetaTitle || fallback.title,
description: dbData?.MetaDesc || fallback.description,
image: dbData?.ImageUrl || fallback.image,
url: route.url,
};
// Read the prerendered HTML file for this specific route
const filePath = path.join(__dirname, "../dist", route.path);
let html;
// ALWAYS use the specific file path, create directory if needed
fs.mkdirSync(path.dirname(filePath), { recursive: true });
if (fs.existsSync(filePath)) {
// If specific file exists, read it
html = fs.readFileSync(filePath, "utf8");
console.log(`Reading existing: ${route.path}`);
} else {
// Copy from base index.html and modify
const baseHtml = fs.readFileSync(
path.join(__dirname, "../dist/index.html"),
"utf8"
);
html = baseHtml;
console.log(`Creating new: ${route.path} from base`);
}
// Replace SEO tags in the HTML
html = html
// Replace title
.replace(/<title>[^<]*<\/title>/g, `<title>${seoData.title}</title>`)
// Replace meta description (handles multiline)
.replace(/<meta name="description"[\s\S]*?>/g, `<meta name="description" content="${seoData.description}" />`)
// Replace OG tags
.replace(/<meta property="og:title" content="[^"]*">/g, `<meta property="og:title" content="${seoData.title}">`)
.replace(/<meta property="og:description"[\s\S]*?>/g, `<meta property="og:description" content="${seoData.description}" />`)
.replace(/<meta property="og:image" content="[^"]*">/g, `<meta property="og:image" content="${seoData.image}">`)
.replace(/<meta property="og:url" content="[^"]*">/g, `<meta property="og:url" content="${seoData.url}">`)
// Replace Twitter tags
.replace(/<meta property="twitter:title" content="[^"]*">/g, `<meta property="twitter:title" content="${seoData.title}">`)
.replace(/<meta property="twitter:description"[\s\S]*?>/g, `<meta property="twitter:description" content="${seoData.description}" />`)
.replace(/<meta property="twitter:image" content="[^"]*">/g, `<meta property="twitter:image" content="${seoData.image}">`)
.replace(/<meta property="twitter:url" content="[^"]*">/g, `<meta property="twitter:url" content="${seoData.url}">`)
// Replace canonical
.replace(/<link rel="canonical" href="[^"]*">/g, `<link rel="canonical" href="${seoData.url}">`);
// Write the updated HTML back to the file
fs.writeFileSync(filePath, html);
console.log(`✓ Generated ${route.path} with unique SEO data`);
console.log(` Title: ${seoData.title.substring(0, 50)}...`);
console.log(` URL: ${seoData.url}`);
console.log(` Image: ${seoData.image}`);
console.log('');
}
console.log("\n✓ All SEO files generated successfully!");
}
generateSEOFiles().catch(console.error);