311 lines
13 KiB
JavaScript
311 lines
13 KiB
JavaScript
import fs from "fs";
|
|
import path from "path";
|
|
import { fileURLToPath } from "url";
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
const mainDirectory = 'https://www.pozo.app';
|
|
|
|
const routes = [
|
|
{ path: "index.html", pageId: 1, url: `${mainDirectory}/`},
|
|
{ path: "signin/index.html", pageId: 2, url: `${mainDirectory}/signin` },
|
|
{ path: "home/pricing-pozoapp/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: "solutions/index.html", pageId: 9, url: `${mainDirectory}/solutions` },
|
|
];
|
|
|
|
const seoData = {
|
|
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.",
|
|
keywords: "retail ERP, POS software, billing software, inventory management, GST billing, kirana store, mini supermarket, weighing scale POS, multi-store ERP, Indian retail software",
|
|
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.",
|
|
keywords: "POZO login, retail ERP login, POS software login, business dashboard, billing software access, inventory management login",
|
|
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.",
|
|
keywords: "POZO pricing, retail ERP pricing, POS software cost, billing software price, inventory management pricing, GST software cost, MSME software pricing",
|
|
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.",
|
|
keywords: "POZO contact, retail ERP support, POS software support, billing software help, inventory management support, customer service, technical support",
|
|
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.",
|
|
keywords: "retail blog, POS guides, billing tutorials, inventory tips, GST billing guide, weighing scale integration, multi-store management, retail technology",
|
|
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.",
|
|
keywords: "about POZO, retail digitization, MSME solutions, Indian retail software, ERP for small business, POS for kirana stores, retail technology company",
|
|
image: `${mainDirectory}/og/about-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.",
|
|
keywords: "retail solutions, comprehensive ERP, POS solutions, billing solutions, inventory solutions, GST compliance software, weighing scale POS, multi-store solutions",
|
|
image: `${mainDirectory}/og/solutions-og.jpg`,
|
|
},
|
|
};
|
|
|
|
async function generateSEOFiles() {
|
|
for (const route of routes) {
|
|
const pageSeo = seoData[route.pageId];
|
|
|
|
const filePath = path.join(__dirname, "../dist", route.path);
|
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
|
|
let html;
|
|
if (fs.existsSync(filePath)) {
|
|
html = fs.readFileSync(filePath, "utf8");
|
|
} else {
|
|
html = fs.readFileSync(path.join(__dirname, "../dist/index.html"), "utf8");
|
|
}
|
|
|
|
// Remove ONLY SEO-specific tags, preserve verification and analytics
|
|
html = html
|
|
.replace(/<meta name="description"[^>]*>/g, '')
|
|
.replace(/<meta name="keywords"[^>]*>/g, '')
|
|
.replace(/<meta property="og:type"[^>]*>/g, '')
|
|
.replace(/<meta property="og:title"[^>]*>/g, '')
|
|
.replace(/<meta property="og:description"[^>]*>/g, '')
|
|
.replace(/<meta property="og:image"[^>]*>/g, '')
|
|
.replace(/<meta property="og:url"[^>]*>/g, '')
|
|
.replace(/<meta property="twitter:card"[^>]*>/g, '')
|
|
.replace(/<meta property="twitter:title"[^>]*>/g, '')
|
|
.replace(/<meta property="twitter:description"[^>]*>/g, '')
|
|
.replace(/<meta property="twitter:image"[^>]*>/g, '')
|
|
.replace(/<meta property="twitter:url"[^>]*>/g, '')
|
|
.replace(/<meta name="twitter:card"[^>]*>/g, '')
|
|
.replace(/<meta name="twitter:title"[^>]*>/g, '')
|
|
.replace(/<meta name="twitter:description"[^>]*>/g, '')
|
|
.replace(/<meta name="twitter:image"[^>]*>/g, '')
|
|
.replace(/<meta name="twitter:url"[^>]*>/g, '')
|
|
.replace(/<link rel="canonical"[^>]*>/g, '');
|
|
|
|
// Replace title
|
|
html = html.replace(/<title>[^<]*<\/title>/g, `<title>${pageSeo.title}</title>`);
|
|
|
|
// Add verification tags and analytics if not present
|
|
const verificationTags = `
|
|
<meta name="msvalidate.01" content="bdb9a09f08f78048c94cb684979cf786" />
|
|
|
|
<!-- Microsoft Clarity -->
|
|
<script type="text/javascript">
|
|
(function (c, l, a, r, i, t, y) {
|
|
c[a] = c[a] || function () { (c[a].q = c[a].q || []).push(arguments) };
|
|
t = l.createElement(r); t.async = 1; t.src = "https://www.clarity.ms/tag/" + i;
|
|
y = l.getElementsByTagName(r)[0]; y.parentNode.insertBefore(t, y);
|
|
})(window, document, "clarity", "script", "u49bg68ikk");
|
|
</script>
|
|
|
|
<!-- Global site tag (gtag.js) - Google Analytics -->
|
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-2QV0HX3QD6"></script>
|
|
<script>
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag() { dataLayer.push(arguments); }
|
|
gtag('js', new Date());
|
|
gtag('config', 'G-2QV0HX3QD6');
|
|
</script>
|
|
|
|
<!-- Google Tag Manager -->
|
|
<script>(function (w, d, s, l, i) {
|
|
w[l] = w[l] || []; w[l].push({
|
|
'gtm.start':
|
|
new Date().getTime(), event: 'gtm.js'
|
|
}); var f = d.getElementsByTagName(s)[0],
|
|
j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src =
|
|
'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f);
|
|
})(window, document, 'script', 'dataLayer', 'GTM-W2NQZPX');</script>
|
|
|
|
<!-- Preconnect for performance -->
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link rel="preconnect" href="https://fonts.cdnfonts.com">
|
|
<link rel="preconnect" href="https://unpkg.com">
|
|
|
|
<link href="https://fonts.cdnfonts.com/css/wasted-vindey" rel="stylesheet" media="print" onload="this.media='all'" />
|
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,400;0,500;0,600;0,700&display=swap" rel="stylesheet" />
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Manrope:wght@400;500;600;700&family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'" />
|
|
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet" />
|
|
|
|
<link rel="sitemap" href="/sitemap.xml" />
|
|
|
|
<!-- Structured Data -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@context":"https://schema.org",
|
|
"@graph":[
|
|
{
|
|
"@type":"Organization",
|
|
"name":"POZO",
|
|
"url":"https://www.pozo.app/",
|
|
"logo":"https://www.pozo.app/src/Images/PozoAppFavicon.png",
|
|
"foundingDate":"2019",
|
|
"contactPoint": {
|
|
"@type": "ContactPoint",
|
|
"telephone": "+91-7324000011",
|
|
"contactType": "customer service"
|
|
},
|
|
"address": {
|
|
"@type": "PostalAddress",
|
|
"streetAddress": "No 51 Step Colony, Dharga",
|
|
"addressLocality": "Hosur",
|
|
"addressRegion": "Tamil Nadu",
|
|
"postalCode": "635126",
|
|
"addressCountry": "IN"
|
|
},
|
|
"sameAs":[]
|
|
},
|
|
{
|
|
"@type":"WebSite",
|
|
"name":"POZO",
|
|
"url":"https://www.pozo.app/",
|
|
"potentialAction":{
|
|
"@type":"SearchAction",
|
|
"target":"https://www.pozo.app/search?q={query}",
|
|
"query-input":"required name=query"
|
|
}
|
|
},
|
|
{
|
|
"@type":"WebPage",
|
|
"url":"${route.url}",
|
|
"name":"${pageSeo.title}",
|
|
"isPartOf":{"@id":"https://www.pozo.app/"},
|
|
"description":"${pageSeo.description}"
|
|
},
|
|
{
|
|
"@type":"SoftwareApplication",
|
|
"name":"POZO - Retail ERP & POS",
|
|
"applicationCategory":"BusinessApplication",
|
|
"operatingSystem":"Windows, Android, iOS",
|
|
"offers":{
|
|
"@type":"Offer",
|
|
"price":"0",
|
|
"priceCurrency":"INR",
|
|
"availability":"https://schema.org/InStock"
|
|
},
|
|
"aggregateRating":{
|
|
"@type":"AggregateRating",
|
|
"ratingValue":"4.8",
|
|
"ratingCount":"150"
|
|
},
|
|
"description":"Complete retail ERP and POS solution for Indian MSMEs with GST billing, inventory management, and multi-store operations.",
|
|
"featureList":[
|
|
"GST Billing",
|
|
"Inventory Management",
|
|
"Multi-store Operations",
|
|
"Weighing Scale Integration",
|
|
"Real-time Analytics",
|
|
"Mobile POS"
|
|
],
|
|
"screenshot":"${pageSeo.image}",
|
|
"softwareVersion":"2.0",
|
|
"author":{
|
|
"@type":"Organization",
|
|
"name":"POZO"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
</script>
|
|
<script src="https://assets.calendly.com/assets/external/widget.js" type="text/javascript"></script>`;
|
|
|
|
// Add all new SEO tags after title
|
|
const newSeoTags = `${verificationTags}
|
|
|
|
<!-- SEO Meta Tags -->
|
|
<meta name="description" content="${pageSeo.description}" />
|
|
<meta name="keywords" content="${pageSeo.keywords}" />
|
|
|
|
<!-- Open Graph / Facebook -->
|
|
<meta property="og:type" content="website" />
|
|
<meta property="og:url" content="${route.url}" />
|
|
<meta property="og:title" content="${pageSeo.title}" />
|
|
<meta property="og:description" content="${pageSeo.description}" />
|
|
<meta property="og:image" content="${pageSeo.image}" />
|
|
|
|
<!-- Twitter -->
|
|
<meta name="twitter:card" content="summary_large_image" />
|
|
<meta name="twitter:url" content="${route.url}" />
|
|
<meta name="twitter:title" content="${pageSeo.title}" />
|
|
<meta name="twitter:description" content="${pageSeo.description}" />
|
|
<meta name="twitter:image" content="${pageSeo.image}" />
|
|
|
|
<link rel="canonical" href="${route.url}" />`;
|
|
|
|
// Only add verification tags if they don't exist
|
|
if (!html.includes('google-site-verification') && !html.includes('gtag')) {
|
|
html = html.replace(/(<title>[^<]*<\/title>)/, `$1${newSeoTags}`);
|
|
} else {
|
|
// Just add SEO tags without verification
|
|
const seoOnlyTags = `
|
|
|
|
<!-- SEO Meta Tags -->
|
|
<meta name="description" content="${pageSeo.description}" />
|
|
<meta name="keywords" content="${pageSeo.keywords}" />
|
|
|
|
<!-- Open Graph / Facebook -->
|
|
<meta property="og:type" content="website" />
|
|
<meta property="og:url" content="${route.url}" />
|
|
<meta property="og:title" content="${pageSeo.title}" />
|
|
<meta property="og:description" content="${pageSeo.description}" />
|
|
<meta property="og:image" content="${pageSeo.image}" />
|
|
|
|
<!-- Twitter -->
|
|
<meta name="twitter:card" content="summary_large_image" />
|
|
<meta name="twitter:url" content="${route.url}" />
|
|
<meta name="twitter:title" content="${pageSeo.title}" />
|
|
<meta name="twitter:description" content="${pageSeo.description}" />
|
|
<meta name="twitter:image" content="${pageSeo.image}" />
|
|
|
|
<link rel="canonical" href="${route.url}" />`;
|
|
html = html.replace(/(<title>[^<]*<\/title>)/, `$1${seoOnlyTags}`);
|
|
}
|
|
|
|
// Add GTM noscript to body if not present
|
|
if (!html.includes('GTM-W2NQZPX')) {
|
|
html = html.replace(
|
|
'<body>',
|
|
`<body>
|
|
<!-- Google Tag Manager (noscript) -->
|
|
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-W2NQZPX" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
|
<!-- End Google Tag Manager (noscript) -->`
|
|
);
|
|
}
|
|
|
|
// Add AOS script before closing body tag
|
|
if (!html.includes('aos.js')) {
|
|
html = html.replace(
|
|
'</body>',
|
|
` <script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
|
</body>`
|
|
);
|
|
}
|
|
|
|
fs.writeFileSync(filePath, html);
|
|
console.log(`✓ Generated ${route.path} with complete SEO`);
|
|
console.log(` Title: ${pageSeo.title}`);
|
|
console.log(` Image: ${pageSeo.image}`);
|
|
console.log(` URL: ${route.url}`);
|
|
console.log('');
|
|
}
|
|
|
|
console.log("✓ All SEO files fixed with verification tags!");
|
|
}
|
|
|
|
generateSEOFiles().catch(console.error); |