E-commerce Product Page Copy Generator
Enter your product details to generate compelling marketing copy.
Product Details
Your generated copy will appear here
Fill in the product details and click "Generate Copy" to get started.
Generating amazing copy...
An Error Occurred
Could not generate copy. Please try again later.
${desc.body}
`).join('') || 'No descriptions generated.
'; case 'bullets': return `- ${data.bullet_points?.map(bullet => `
- ${bullet} `).join('') || '
- No bullet points generated. '}
Meta Description
${data.meta_description || 'No meta description generated.'}
`; case 'social': return `- ${data.social_media_posts?.map(post => `
- ${post} `).join('') || '
- No social media posts generated. '}
No content available.
'; } } function getDataForTab(tabId, data) { if (!data) return null; switch (tabId) { case 'titles': return data.product_titles; case 'descriptions': return data.product_descriptions; case 'bullets': return data.bullet_points; case 'meta': return data.meta_description; case 'social': return data.social_media_posts; default: return null; } } function showTab(index) { if (!tabsContainer || !tabContentsContainer) return; const tabs = tabsContainer.querySelectorAll('.tab'); const contents = tabContentsContainer.querySelectorAll('.tab-content'); tabs.forEach(tab => tab.classList.remove('active')); contents.forEach(content => content.classList.remove('active')); if(tabs[index]) tabs[index].classList.add('active'); if(contents[index]) contents[index].classList.add('active'); currentTabIndex = index; updateNavButtons(); } function navigateTabs(direction) { const newIndex = currentTabIndex + direction; if (newIndex >= 0 && newIndex < tabConfig.length) { showTab(newIndex); } } function updateNavButtons() { if (!prevTabBtn || !nextTabBtn) return; prevTabBtn.disabled = currentTabIndex === 0; nextTabBtn.disabled = currentTabIndex === tabConfig.length - 1; } function generatePdf() { if (!window.jspdf || !latestGeneratedData) { alert("Please generate content before downloading a PDF."); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pageHeight = doc.internal.pageSize.getHeight(); const pageWidth = doc.internal.pageSize.getWidth(); const margin = 40; const contentWidth = pageWidth - margin * 2; let cursorY = margin; let pageCount = 1; const addHeader = () => { doc.setFontSize(9); doc.setTextColor(150); doc.text("E-commerce Product Copy Report", margin, margin - 18); const date = new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }); doc.text(date, pageWidth - margin, margin - 18, { align: 'right' }); doc.setDrawColor(220); doc.line(margin, margin - 10, pageWidth - margin, margin - 10); }; const addFooter = () => { doc.setFontSize(8); doc.setTextColor(150); doc.text(`Page ${pageCount}`, pageWidth / 2, pageHeight - 20, { align: 'center' }); }; const checkPageBreak = (neededHeight) => { if (cursorY + neededHeight > pageHeight - margin) { addFooter(); doc.addPage(); pageCount++; cursorY = margin; addHeader(); } }; // --- PDF Content Generation --- addHeader(); doc.setFontSize(22); doc.setTextColor(30, 30, 30); doc.setFont("helvetica", "bold"); const mainTitle = productNameEl.value || "Generated Copy"; const splitTitle = doc.splitTextToSize(mainTitle, contentWidth); checkPageBreak(splitTitle.length * 22); doc.text(splitTitle, pageWidth / 2, cursorY + 10, { align: 'center' }); cursorY += (splitTitle.length * 22) + 25; tabConfig.forEach(tab => { const dataForTab = getDataForTab(tab.id, latestGeneratedData); if (!dataForTab || (Array.isArray(dataForTab) && dataForTab.length === 0)) return; checkPageBreak(40); doc.setFontSize(14); doc.setFont("helvetica", "bold"); doc.setTextColor(79, 70, 229); // Indigo color doc.text(tab.name, margin, cursorY); cursorY += 10; doc.setDrawColor(200); doc.line(margin, cursorY, margin + 120, cursorY); cursorY += 15; doc.setFontSize(10); doc.setFont("helvetica", "normal"); doc.setTextColor(51, 51, 51); const lineHeight = 12; switch (tab.id) { case 'titles': case 'bullets': case 'social': dataForTab.forEach(item => { const lines = doc.splitTextToSize(`• ${item}`, contentWidth - 15); checkPageBreak(lines.length * lineHeight + 5); doc.text(lines, margin + 15, cursorY); cursorY += (lines.length * lineHeight) + 6; }); break; case 'descriptions': dataForTab.forEach(desc => { doc.setFont("helvetica", "bold"); const headingLines = doc.splitTextToSize(desc.heading, contentWidth); checkPageBreak(headingLines.length * lineHeight + 2); doc.text(headingLines, margin, cursorY); cursorY += (headingLines.length * lineHeight) + 4; doc.setFont("helvetica", "normal"); const bodyLines = doc.splitTextToSize(desc.body, contentWidth); checkPageBreak(bodyLines.length * lineHeight + 15); doc.text(bodyLines, margin, cursorY); cursorY += (bodyLines.length * lineHeight) + 15; }); break; case 'meta': const lines = doc.splitTextToSize(dataForTab, contentWidth); checkPageBreak(lines.length * lineHeight + 15); doc.text(lines, margin, cursorY); cursorY += (lines.length * lineHeight) + 15; break; } cursorY += 10; // Space between sections }); addFooter(); doc.save(`${productNameEl.value.replace(/ /g, '_')}_copy_report.pdf`); } setUIState('placeholder'); addFeatureInput(); // Start with one feature/benefit row });