import process from 'node:process'; import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); function stripHtml(html: string): string { return html.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim(); } async function runSeoBackfill() { console.log('🚀 Starting SEO & Content Backfill Script for Canina Iran...\n'); // 1. Backfill Products const products = await prisma.product.findMany(); console.log(`📦 Found ${products.length} products to check...`); let updatedProducts = 0; for (const product of products) { const dataToUpdate: Record = {}; if (!product.metaTitle || product.metaTitle.trim() === '') { dataToUpdate.metaTitle = `${product.nameFa} (${product.packageSize} ${product.unit}) | کنینا ایران`; } if (!product.metaDescription || product.metaDescription.trim() === '') { const baseDesc = product.shortDescription || stripHtml(product.description || ''); const cleanDesc = baseDesc.substring(0, 150).trim(); dataToUpdate.metaDescription = cleanDesc ? `${cleanDesc} | خرید اینترنتی با ضمانت اصالت کنینا آلمان.` : `خرید آنلاین ${product.nameFa} با ضمانت ۱۰۰٪ اصالت آلمان و ارسال سریع در کنینا ایران.`; } if (!product.featuredImageAlt || product.featuredImageAlt.trim() === '') { dataToUpdate.featuredImageAlt = `مکمل دارویی ${product.nameFa} Canina آلمان`; } if (!product.keywords || product.keywords.trim() === '') { const tags = [ product.nameFa, product.nameEn, `مکمل ${product.suitableFor}`, 'کنینا آلمان', 'Canina', product.categorySlug, ].filter(Boolean); dataToUpdate.keywords = tags.join(', '); } if (Object.keys(dataToUpdate).length > 0) { await prisma.product.update({ where: { id: product.id }, data: dataToUpdate, }); updatedProducts++; } } console.log(`✅ Products backfill complete: ${updatedProducts} products updated.\n`); // 2. Backfill Blogs & Cross-Linking const blogs = await prisma.blog.findMany(); console.log(`📰 Found ${blogs.length} blog posts to check...`); let updatedBlogs = 0; for (const blog of blogs) { const dataToUpdate: Record = {}; if (!blog.metaTitle || blog.metaTitle.trim() === '') { dataToUpdate.metaTitle = `${blog.title} | مجله تخصصی کنینا`; } if (!blog.metaDescription || blog.metaDescription.trim() === '') { const baseExcerpt = blog.excerpt || stripHtml(blog.content || ''); dataToUpdate.metaDescription = baseExcerpt.substring(0, 155).trim(); } if (!blog.imageAlt || blog.imageAlt.trim() === '') { dataToUpdate.imageAlt = `تصویر راهنمای تخصصی ${blog.title}`; } // Auto Cross-Linking: If relatedProductIds is empty, match top products by category or title keywords if (!blog.relatedProductIds || blog.relatedProductIds.length === 0) { const keywords = [blog.title, blog.keywords].filter(Boolean).join(' '); const matchingProducts = await prisma.product.findMany({ where: { OR: [ { categorySlug: { contains: blog.categoryId || '', mode: 'insensitive' } }, { nameFa: { contains: blog.title.split(' ')[0] || '', mode: 'insensitive' } }, { description: { contains: blog.title.split(' ')[0] || '', mode: 'insensitive' } }, ], }, take: 3, select: { id: true }, }); if (matchingProducts.length > 0) { dataToUpdate.relatedProductIds = matchingProducts.map((p) => p.id); } else { // Fallback: pick top 2 featured products const topProducts = await prisma.product.findMany({ take: 2, select: { id: true } }); dataToUpdate.relatedProductIds = topProducts.map((p) => p.id); } } if (Object.keys(dataToUpdate).length > 0) { await prisma.blog.update({ where: { id: blog.id }, data: dataToUpdate, }); updatedBlogs++; } } console.log(`✅ Blog posts backfill complete: ${updatedBlogs} posts updated with SEO & cross-links.\n`); console.log('🎉 SEO Backfill and Internal Cross-Linking finished successfully!'); } runSeoBackfill() .catch((e) => { console.error('❌ SEO Backfill failed:', e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });