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:
@@ -0,0 +1,157 @@
|
||||
import type {
|
||||
ProjectRow,
|
||||
ServiceRow,
|
||||
SiteSettingsRow,
|
||||
FaqItem,
|
||||
} from "@/lib/types";
|
||||
import { siteConfig } from "@/lib/site-config";
|
||||
|
||||
export function JsonLd({ data }: { data: object }) {
|
||||
return (
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function OrganizationLd({
|
||||
settings,
|
||||
}: {
|
||||
settings?: SiteSettingsRow | null;
|
||||
}) {
|
||||
const phone = settings?.contact_phone_raw ?? siteConfig.contact.phoneRaw;
|
||||
const email = settings?.contact_email ?? siteConfig.contact.email;
|
||||
const address = settings?.contact_address ?? siteConfig.contact.address;
|
||||
const socials = [
|
||||
settings?.social_linkedin,
|
||||
settings?.social_instagram,
|
||||
settings?.social_twitter,
|
||||
settings?.social_facebook,
|
||||
].filter(Boolean);
|
||||
|
||||
const data: Record<string, unknown> = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "LocalBusiness",
|
||||
"@id": `${siteConfig.url}/#organization`,
|
||||
name: settings?.site_name ?? siteConfig.name,
|
||||
description: settings?.footer_tagline ?? siteConfig.tagline,
|
||||
url: siteConfig.url,
|
||||
logo: `${siteConfig.url}/logo.png`,
|
||||
image: `${siteConfig.url}/logo.png`,
|
||||
telephone: phone,
|
||||
email,
|
||||
address: {
|
||||
"@type": "PostalAddress",
|
||||
streetAddress: address,
|
||||
addressLocality: "İzmit",
|
||||
addressRegion: "Kocaeli",
|
||||
addressCountry: "TR",
|
||||
},
|
||||
areaServed: [
|
||||
{ "@type": "City", name: "Kocaeli" },
|
||||
{ "@type": "City", name: "İstanbul" },
|
||||
{ "@type": "Country", name: "Türkiye" },
|
||||
],
|
||||
sameAs: socials,
|
||||
};
|
||||
|
||||
if (settings?.google_rating && settings?.google_review_count) {
|
||||
data.aggregateRating = {
|
||||
"@type": "AggregateRating",
|
||||
ratingValue: settings.google_rating,
|
||||
reviewCount: settings.google_review_count,
|
||||
bestRating: 5,
|
||||
worstRating: 1,
|
||||
};
|
||||
}
|
||||
|
||||
return <JsonLd data={data} />;
|
||||
}
|
||||
|
||||
export function ServiceLd({
|
||||
service,
|
||||
settings,
|
||||
}: {
|
||||
service: ServiceRow;
|
||||
settings?: SiteSettingsRow | null;
|
||||
}) {
|
||||
return (
|
||||
<JsonLd
|
||||
data={{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Service",
|
||||
serviceType: service.title,
|
||||
name: service.title,
|
||||
description: service.description,
|
||||
provider: {
|
||||
"@type": "LocalBusiness",
|
||||
name: settings?.site_name ?? siteConfig.name,
|
||||
url: siteConfig.url,
|
||||
},
|
||||
areaServed: { "@type": "Country", name: "Türkiye" },
|
||||
url: `${siteConfig.url}/hizmetler/${service.slug}`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function FaqLd({ items }: { items: FaqItem[] }) {
|
||||
if (items.length === 0) return null;
|
||||
return (
|
||||
<JsonLd
|
||||
data={{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "FAQPage",
|
||||
mainEntity: items.map((it) => ({
|
||||
"@type": "Question",
|
||||
name: it.q,
|
||||
acceptedAnswer: {
|
||||
"@type": "Answer",
|
||||
text: it.a,
|
||||
},
|
||||
})),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function BreadcrumbLd({
|
||||
items,
|
||||
}: {
|
||||
items: { name: string; url: string }[];
|
||||
}) {
|
||||
return (
|
||||
<JsonLd
|
||||
data={{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
itemListElement: items.map((it, i) => ({
|
||||
"@type": "ListItem",
|
||||
position: i + 1,
|
||||
name: it.name,
|
||||
item: it.url,
|
||||
})),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function ArticleLd({ post }: { post: ProjectRow }) {
|
||||
return (
|
||||
<JsonLd
|
||||
data={{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Article",
|
||||
headline: post.title,
|
||||
description: post.description,
|
||||
image: post.image_url,
|
||||
author: {
|
||||
"@type": "Organization",
|
||||
name: siteConfig.name,
|
||||
url: siteConfig.url,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user