feat: TR reklam trafiği için anasayfa CRO optimizasyonu
Yeni bölümler ve component'ler: - WhatsAppFloat: sağ altta her sayfada görünen 'pulse' animasyonlu WhatsApp butonu - MobileCtaBar: mobilde alt sabit bar — Ara / WhatsApp / Teklif Al üç buton - TrustBand: hero altı 4 trust kartı (Google ★, proje sayısı, dönüş süresi, garanti) + Google rating + yorum sayısı satırı - LogoCloud: müşteri logoları grayscale strip - QuickLeadForm: ad + telefon iki alanlı inline mini form (anasayfada) - app/actions submitContact 'source' alanını destekliyor (quick lead → message zorunlu değil) - WhyUs: 4 USP kartı (Hızlı teslim, Yerel destek, Modern tech, Satış sonrası) - ProcessSteps: 4 adımlı 'nasıl çalışıyoruz' süreç akışı (numaralı timeline) Schema (JSON-LD): - OrganizationLd: LocalBusiness + Address + AggregateRating (Google review puanı/sayısı) - ServiceLd: hizmet detay sayfaları için - FaqLd: hizmet FAQ'leri için - BreadcrumbLd, ArticleLd: hazır Anasayfaya OrganizationLd ekli — Google Ads quality score + organic rich results. Performans: - REST GET çağrıları cache:'no-store' yerine next.revalidate=60 (ISR) - Public sayfalar artık static rendering — LCP düşer - Mutations ve session GET'ler hâlâ no-store site_settings yeni alanları (panelden yönetilebilir): - whatsapp_message (default WhatsApp opener) - client_logos[] (logo URL listesi) - trust_items[] (JSON: icon|value|label) - why_us[] (JSON: icon, title, description) - process_steps[] (JSON: title, description) - lead_form_title, lead_form_description - google_rating, google_review_count, google_review_url Admin /admin/site formuna yeni 'Conversion / reklam optimizasyonu', 'Neden Biz?' ve 'Süreç adımları' bölümleri eklendi. Mevcut anasayfa yapısı (üstten alta): 1. Hero 2. TrustBand (mini güven sinyalleri) 3. LogoCloud (varsa müşteri logoları) 4. Hızlı iletişim + QuickLeadForm (2 sütun: tel/WA CTA + mini form) 5. Hizmetler 6. WhyUs (Neden Biz?) 7. ProcessSteps (Nasıl çalışıyoruz?) 8. Projeler 9. Testimonials 10. CTA (Final + WhatsApp)
This commit is contained in:
@@ -297,6 +297,57 @@ export async function saveSiteSettings(formData: FormData) {
|
||||
})
|
||||
.filter((x): x is string => x !== null);
|
||||
|
||||
// Trust items: "icon|value|label" satırlar
|
||||
const trustRaw = String(formData.get("trust_items") ?? "");
|
||||
const trust = trustRaw
|
||||
.split("\n")
|
||||
.map((line) => {
|
||||
const [icon, value, label] = line.split("|").map((s) => s.trim());
|
||||
if (!value || !label) return null;
|
||||
return JSON.stringify({ icon: icon || "Sparkles", value, label });
|
||||
})
|
||||
.filter((x): x is string => x !== null);
|
||||
|
||||
// Why us / Process: blok '---' ile ayrılır; her blok için:
|
||||
// why_us: ilk satır = icon|title, kalanı description
|
||||
// process: ilk satır = title, kalanı description
|
||||
function parseBlocks(raw: string, withIcon: boolean): string[] {
|
||||
return raw
|
||||
.split("\n---\n")
|
||||
.map((block) => {
|
||||
const lines = block.trim().split("\n");
|
||||
if (lines.length < 2) return null;
|
||||
if (withIcon) {
|
||||
const [icon, title] = lines[0].split("|").map((s) => s.trim());
|
||||
const description = lines.slice(1).join("\n").trim();
|
||||
if (!title || !description) return null;
|
||||
return JSON.stringify({
|
||||
icon: icon || "Sparkles",
|
||||
title,
|
||||
description,
|
||||
});
|
||||
}
|
||||
const title = lines[0].trim();
|
||||
const description = lines.slice(1).join("\n").trim();
|
||||
if (!title || !description) return null;
|
||||
return JSON.stringify({ title, description });
|
||||
})
|
||||
.filter((x): x is string => x !== null);
|
||||
}
|
||||
|
||||
const whyUs = parseBlocks(String(formData.get("why_us") ?? ""), true);
|
||||
const processSteps = parseBlocks(
|
||||
String(formData.get("process_steps") ?? ""),
|
||||
false,
|
||||
);
|
||||
|
||||
// Client logos: her satıra bir URL
|
||||
const logosRaw = String(formData.get("client_logos") ?? "");
|
||||
const logos = logosRaw
|
||||
.split("\n")
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
const data = {
|
||||
hero_badge: str(formData.get("hero_badge")),
|
||||
hero_title: str(formData.get("hero_title")),
|
||||
@@ -337,6 +388,17 @@ export async function saveSiteSettings(formData: FormData) {
|
||||
social_facebook: str(formData.get("social_facebook")),
|
||||
|
||||
footer_tagline: str(formData.get("footer_tagline")),
|
||||
|
||||
whatsapp_message: str(formData.get("whatsapp_message")),
|
||||
client_logos: logos.length > 0 ? logos : null,
|
||||
trust_items: trust.length > 0 ? trust : null,
|
||||
why_us: whyUs.length > 0 ? whyUs : null,
|
||||
process_steps: processSteps.length > 0 ? processSteps : null,
|
||||
lead_form_title: str(formData.get("lead_form_title")),
|
||||
lead_form_description: str(formData.get("lead_form_description")),
|
||||
google_review_url: str(formData.get("google_review_url")),
|
||||
google_rating: num(formData.get("google_rating")),
|
||||
google_review_count: num(formData.get("google_review_count")),
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user