← back to Consulting Designerwallcoverings Com

scripts/aeo-build-jsonld-snippet.mjs

97 lines

#!/usr/bin/env node
// TK-20 — Build the DRAFT handle-keyed theme snippet `dw-aeo-jsonld.liquid`
// from the committed docs/aeo-drafts/*.jsonld files, so the FAQPage schema the
// snippet emits stays in EXACT sync with the reviewed/approved draft content.
// DRAFT-ONLY: writes a .liquid file into the repo. It performs NO theme write.
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const DRAFTS = path.join(ROOT, 'docs/aeo-drafts');
const OUT = path.join(DRAFTS, 'theme-snippets', 'dw-aeo-jsonld.liquid');

// handle → { file, template } . template = 'collection' | 'page'
const MAP = [
  { handle: 'versace-wallpaper',   file: 'versace-wallpaper.jsonld',   template: 'collection' },
  { handle: 'osborne-little',      file: 'osborne-and-little.jsonld',  template: 'collection' },
  { handle: 'zuber-wallcoverings', file: 'zuber-wallpaper.jsonld',     template: 'collection' },
  { handle: 'wall-coverings',      file: 'wall-coverings.jsonld',      template: 'page' },
  { handle: 'designer-wallpaper',  file: 'designer-wallpaper.jsonld',  template: 'page' },
];

const read = f => JSON.parse(fs.readFileSync(path.join(DRAFTS, f), 'utf8'));

// From a committed graph, keep only the schema nodes that are SAFE to add without
// duplicating what the theme already emits:
//  - pages   : WebPage + FAQPage  (sections/page.liquid emits neither)
//  - collections: FAQPage ONLY    (sections/dw-collection-hero.liquid already
//                 emits CollectionPage + BreadcrumbList; we must NOT re-emit them)
function schemaFor(entry) {
  const j = read(entry.file);
  const graph = (j['@graph'] || []).filter(n => {
    if (n['@type'] === 'FAQPage') return true;
    if (entry.template === 'page' && n['@type'] === 'WebPage') return true;
    return false; // drop CollectionPage on collections (theme already emits it)
  });
  return { '@context': 'https://schema.org', '@graph': graph };
}

let cases = '';
for (const e of MAP) {
  const obj = schemaFor(e);
  // pretty JSON, indented under the script tag
  const jsonStr = JSON.stringify(obj, null, 2).split('\n').map(l => '    ' + l).join('\n');
  const guard = e.template === 'collection'
    // only emit if the theme's metafield-driven FAQ is NOT set, to avoid a
    // duplicate FAQPage (dw-collection-hero emits FAQPage from custom.faq).
    ? `    {%- assign _mf_faq = collection.metafields.custom.faq.value -%}\n    {%- if _mf_faq == blank -%}`
    : `    {%- comment -%} page: theme emits no FAQPage; safe to emit {%- endcomment -%}`;
  const close = e.template === 'collection' ? `    {%- endif -%}\n` : ``;
  cases += `  {%- when '${e.handle}' -%}\n${guard}\n    <script type="application/ld+json">\n${jsonStr}\n    </script>\n${close}`;
}

const snippet = `{%- comment -%}
  dw-aeo-jsonld.liquid  —  DRAFT (TK-20, DW consulting)  —  do NOT inject until Steve GO.

  Emits the reviewed/approved FAQPage (and WebPage for landing pages) JSON-LD for the
  striking-distance AEO targets, KEYED ON HANDLE. Generated from the committed
  docs/aeo-drafts/*.jsonld by scripts/aeo-build-jsonld-snippet.mjs — regenerate, do not
  hand-edit, so the schema stays in sync with the approved copy.

  WHY THIS SNIPPET EXISTS
  -----------------------
  * PAGES (/pages/wall-coverings, /pages/designer-wallpaper): sections/page.liquid renders
    page.content visibly but emits NO FAQPage/WebPage JSON-LD. This snippet supplies it.
  * COLLECTIONS (versace-wallpaper, osborne-little, zuber-wallcoverings): the theme ALREADY
    emits FAQPage + CollectionPage + BreadcrumbList from sections/dw-collection-hero.liquid
    when the collection's custom.faq metafield is populated. The RECOMMENDED path for
    collections is therefore to WRITE THE METAFIELDS (see the memo), not this snippet.
    The collection branches below are a FALLBACK — they emit FAQPage ONLY, and only when
    custom.faq is blank, so they never double-emit.

  INSTALL (both are Steve-gated theme writes — see the memo for exact PUT commands):
    1. PUT this file to  snippets/dw-aeo-jsonld.liquid  on the live theme.
    2. Add  {% render 'dw-aeo-jsonld' %}  near the end of  sections/page.liquid
       (covers pages). For the collection fallback, also add it to
       sections/dw-collection-hero.liquid (guarded branch handles the dedupe).
{%- endcomment -%}
{%- liquid
  assign _tpl = template.name
  if _tpl == 'page'
    assign _aeo_handle = page.handle
  elsif _tpl == 'collection'
    assign _aeo_handle = collection.handle
  else
    assign _aeo_handle = ''
  endif
-%}
{%- case _aeo_handle -%}
${cases}  {%- else -%}
{%- endcase -%}
`;

fs.mkdirSync(path.dirname(OUT), { recursive: true });
fs.writeFileSync(OUT, snippet);
console.log('wrote', path.relative(ROOT, OUT), `(${snippet.length} bytes, ${MAP.length} handles)`);