You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I work at Deco.cx and here we created a feature called "Async Rendering" that renders sections of the website asynchronously, a "Skeleton" of the HTML is sent to the client as quickly as possible, while other sections that depend on data from external APIs are rendered asynchronously and returned to the client after resolution. One of the frameworks we use is Fresh and for this feature we use "partials" to return the component to the client.
Basically this is the fresh implementation
We recently found a problem with this feature, our SEO components were not adding structured data to the HTML when async rendering is active in this component, and after some investigations I found where this problem could be happening. This is our SEO component:
import{Head}from"$fresh/runtime.ts";importtype{ImageWidget}from"../../admin/widgets.ts";import{stripHTML}from"../utils/html.ts";import{JSX}from"preact";exportconstrenderTemplateString=(template: string,value: string)=>template.replace("%s",value);exporttypeSEOSection=JSX.Element;exporttypeOGType="website"|"article";exportinterfaceProps{title?: string;/** * @title Title template * @description add a %s whenever you want it to be replaced with the product name, category name or search term * @default %s */titleTemplate?: string;description?: string;/** * @title Description template * @description add a %s whenever you want it to be replaced with the product name, category name or search term * @default %s */descriptionTemplate?: string;/** @default website */type?: OGType;/** @description Recommended: 1200 x 630 px (up to 5MB) */image?: ImageWidget;/** @description Recommended: 16 x 16 px */favicon?: ImageWidget;/** @description Suggested color that browsers should use to customize the display of the page or of the surrounding user interface */themeColor?: string;/** @title Canonical URL */canonical?: string;/** * @title Disable indexing * @description In testing, you can use this to prevent search engines from indexing your site */noIndexing?: boolean;jsonLDs?: unknown[];}functionComponent({title: t="",
titleTemplate ="%s",description: desc,
descriptionTemplate ="%s",
type,
image,
favicon,
themeColor,
canonical,
noIndexing,
jsonLDs =[],}: Props){consttwitterCard=type==="website" ? "summary" : "summary_large_image";constdescription=stripHTML(desc||"");consttitle=stripHTML(t);return(<Head><title>{renderTemplateString(titleTemplate,title)}</title><metaname="description"content={renderTemplateString(descriptionTemplate,description)}/><metaname="theme-color"content={themeColor}/><linkrel="icon"href={favicon}/>{/* Twitter tags */}<metaproperty="twitter:title"content={title}/><metaproperty="twitter:description"content={description}/><metaproperty="twitter:image"content={image}/><metaproperty="twitter:card"content={twitterCard}/>{/* OpenGraph tags */}<metaproperty="og:title"content={title}/><metaproperty="og:description"content={description}/><metaproperty="og:type"content={type}/><metaproperty="og:image"content={image}/>{/* Link tags */}{canonical&&<linkrel="canonical"href={canonical}/>}{/* No index, no follow */}{noIndexing&&<metaname="robots"content="noindex, nofollow"/>}{!noIndexing&&<metaname="robots"content="index, follow"/>}{jsonLDs.map((json)=>(<scripttype="application/ld+json"dangerouslySetInnerHTML={{__html: JSON.stringify({"@context": "https://schema.org",// @ts-expect-error Trust me, I'm an engineer
...json,}),}}/>))}</Head>);}exportdefaultComponent;
The structured data is passed as "jsonLDs" props and added to the <Head> component inside a <script> tag, looking for the partials implementation I've find out that the implementation ignores scripts inside the "head" element:
Another important point that I forgot to mention, when I remove the script from <Head> and start sending it in the body, the script is added to the document but it comes without any content, I haven't discovered the exact cause yet but I'm seeing what could be happening
I work at Deco.cx and here we created a feature called "Async Rendering" that renders sections of the website asynchronously, a "Skeleton" of the HTML is sent to the client as quickly as possible, while other sections that depend on data from external APIs are rendered asynchronously and returned to the client after resolution. One of the frameworks we use is Fresh and for this feature we use "partials" to return the component to the client.
Basically this is the fresh implementation

We recently found a problem with this feature, our SEO components were not adding structured data to the HTML when async rendering is active in this component, and after some investigations I found where this problem could be happening. This is our SEO component:
The structured data is passed as "jsonLDs" props and added to the
<Head>
component inside a<script>
tag, looking for the partials implementation I've find out that the implementation ignores scripts inside the "head" element:fresh/src/runtime/client/partials.ts
Lines 393 to 397 in 70d6cbd
We need that these scripts are pushed to the actual document's head so the crawlers can read these scripts and improve our websites SEO.
I'm willing to contribute to this problem, I just need to be sure how we can fix this without causing problems
The text was updated successfully, but these errors were encountered: