add SEO enhancements: OG images, meta robots, FAQ block, image sitemap
All checks were successful
deploy / deploy (push) Successful in 4m59s
All checks were successful
deploy / deploy (push) Successful in 4m59s
- Per-page SEO controls: meta robots directives, focus keyword, OG image - Site-wide default OG image in admin settings - FAQ block type with FAQPage JSON-LD schema - Enhanced Organization JSON-LD with business info, contact, address - Image sitemap with product images - SEO preview panel with Google/social card mockups - SEO checklist with real-time scoring - Business info section in site editor - GSC integration scaffolding (OAuth, client, cache) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -64,6 +64,7 @@ defmodule BerrypodWeb.ShopComponents.SiteEditor do
|
||||
|> assign(:header_nav, state.header_nav)
|
||||
|> assign(:footer_nav, state.footer_nav)
|
||||
|> assign(:social_links, state.social_links)
|
||||
|> assign(:business_info, state.business_info)
|
||||
|
||||
~H"""
|
||||
<div class="editor-site-content">
|
||||
@@ -109,6 +110,10 @@ defmodule BerrypodWeb.ShopComponents.SiteEditor do
|
||||
<.site_section title="Social links" icon="hero-link">
|
||||
<.social_links_editor links={@social_links} event_prefix={@event_prefix} />
|
||||
</.site_section>
|
||||
|
||||
<.site_section title="Business info" icon="hero-building-storefront">
|
||||
<.business_info_editor info={@business_info} event_prefix={@event_prefix} />
|
||||
</.site_section>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
@@ -856,6 +861,144 @@ defmodule BerrypodWeb.ShopComponents.SiteEditor do
|
||||
"""
|
||||
end
|
||||
|
||||
# ── Business Info Editor ────────────────────────────────────────────
|
||||
|
||||
attr :info, :map, required: true
|
||||
attr :event_prefix, :string, default: "site_"
|
||||
|
||||
defp business_info_editor(assigns) do
|
||||
~H"""
|
||||
<form class="site-editor-form" phx-change={@event_prefix <> "update_business_info"}>
|
||||
<p class="admin-text-secondary admin-text-sm" style="margin-bottom: 1rem;">
|
||||
Used for rich snippets in search results and business schema data.
|
||||
</p>
|
||||
|
||||
<div class="theme-section">
|
||||
<label class="theme-section-label">Business type</label>
|
||||
<div class="site-editor-radio-group">
|
||||
<label class="admin-radio-label">
|
||||
<input
|
||||
type="radio"
|
||||
name="business_info[business_type]"
|
||||
value="Organization"
|
||||
checked={@info["business_type"] != "LocalBusiness"}
|
||||
/>
|
||||
<span>Organisation</span>
|
||||
</label>
|
||||
<label class="admin-radio-label">
|
||||
<input
|
||||
type="radio"
|
||||
name="business_info[business_type]"
|
||||
value="LocalBusiness"
|
||||
checked={@info["business_type"] == "LocalBusiness"}
|
||||
/>
|
||||
<span>Local business</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="theme-section">
|
||||
<label class="theme-section-label" for="business-phone">Phone</label>
|
||||
<input
|
||||
type="tel"
|
||||
id="business-phone"
|
||||
name="business_info[business_phone]"
|
||||
value={@info["business_phone"]}
|
||||
class="admin-input"
|
||||
placeholder="+44 7123 456789"
|
||||
phx-debounce="500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="theme-section">
|
||||
<label class="theme-section-label" for="business-email">Email</label>
|
||||
<input
|
||||
type="email"
|
||||
id="business-email"
|
||||
name="business_info[business_email]"
|
||||
value={@info["business_email"]}
|
||||
class="admin-input"
|
||||
placeholder="hello@example.com"
|
||||
phx-debounce="500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<%!-- Address fields shown for LocalBusiness --%>
|
||||
<div
|
||||
class="business-address-fields"
|
||||
style={if @info["business_type"] != "LocalBusiness", do: "display: none;"}
|
||||
>
|
||||
<div class="theme-section">
|
||||
<label class="theme-section-label" for="business-street">Street address</label>
|
||||
<input
|
||||
type="text"
|
||||
id="business-street"
|
||||
name="business_info[address_street]"
|
||||
value={@info["address_street"]}
|
||||
class="admin-input"
|
||||
placeholder="123 High Street"
|
||||
phx-debounce="500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="theme-section">
|
||||
<label class="theme-section-label" for="business-city">City</label>
|
||||
<input
|
||||
type="text"
|
||||
id="business-city"
|
||||
name="business_info[address_city]"
|
||||
value={@info["address_city"]}
|
||||
class="admin-input"
|
||||
placeholder="London"
|
||||
phx-debounce="500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="admin-row admin-row-sm">
|
||||
<div class="theme-section admin-fill">
|
||||
<label class="theme-section-label" for="business-region">County / region</label>
|
||||
<input
|
||||
type="text"
|
||||
id="business-region"
|
||||
name="business_info[address_region]"
|
||||
value={@info["address_region"]}
|
||||
class="admin-input"
|
||||
placeholder="Greater London"
|
||||
phx-debounce="500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="theme-section" style="flex: 0 0 8rem;">
|
||||
<label class="theme-section-label" for="business-postcode">Postcode</label>
|
||||
<input
|
||||
type="text"
|
||||
id="business-postcode"
|
||||
name="business_info[address_postal_code]"
|
||||
value={@info["address_postal_code"]}
|
||||
class="admin-input"
|
||||
placeholder="SW1A 1AA"
|
||||
phx-debounce="500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="theme-section">
|
||||
<label class="theme-section-label" for="business-country">Country</label>
|
||||
<input
|
||||
type="text"
|
||||
id="business-country"
|
||||
name="business_info[address_country]"
|
||||
value={@info["address_country"]}
|
||||
class="admin-input"
|
||||
placeholder="United Kingdom"
|
||||
phx-debounce="500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
"""
|
||||
end
|
||||
|
||||
# ── Helpers ─────────────────────────────────────────────────────────
|
||||
|
||||
# Social
|
||||
|
||||
Reference in New Issue
Block a user