npm package: @sparrowengg/payloadcms-plugin-structured-data-generator
Description: Structured Data Generator payload plugin (bundled with tsup)
Author: Pranav K S
Latest version: 0.1.11

# @sparrowengg/payloadcms-plugin-structured-data-generator

Internal Payload CMS plugin of SurveySparrow for generating Structured Data using AI.

## Requirements

This package has the following peer dependencies. Make sure you have these:

```json
"payload": "^3.59.1",
"@payloadcms/ui": "^3.59.1"
```

## Installation

### 1. Install the package

```bash
pnpm add @sparrowengg/payloadcms-plugin-structured-data-generator
```

### 2. Environment Variables

In your `.env` file, add the following environment variables:

```env
NEXT_PUBLIC_SERVER_URL=https://www.yoursite.com
NEXT_PUBLIC_AI_STRUCTURED_DATA_API=<Get value from AI team>
```

### 3. Add Route Handlers

The plugin makes use of Payload's server-side lexical-markdown conversion helper.

Add the following route handlers under `app/(payload)/api/` folder:

#### `/api/convert-lexical-to-markdown/route.ts`

```typescript
import config from '@payload-config';
import { convertLexicalToMarkdown } from '@payloadcms/richtext-lexical';
import type { SerializedEditorState } from '@payloadcms/richtext-lexical/lexical';

export async function POST(request: Request) {
  const data: SerializedEditorState = await request.json();

  const editorConfig = ((await config).editor as any)?.editorConfig || {};
  const markdown = convertLexicalToMarkdown({
    data,
    editorConfig,
  });

  return new Response(JSON.stringify(markdown));
}
```

## Usage

### 1. Add field name mappings

Create a field name mapping file at `/payload/plugins/config/structuredDataGenerator/fieldNameMappings.ts` to assign the correct fields for api payload.

```typescript
export const fieldNameMappings = {
  common: {
    metaDescription: 'meta.description', // Use dot operator for nested paths
    name: 'populatedAuthors[0].name',
    publishedAt: 'publishedAt',
    faqSection: 'faq',
  },
  individualCollections: { // Optional - no need to add this if field names are 'title' & 'content' (example below)
    // blogs: {
    //   title: 'title',
    //   blogContent: 'content',
    // },
    'sales-glossary': { // Add this if your title & content field names are different
      title: 'glossaryName',
      blogContent: 'glossaryContent',
    },
  }
```

### 2. Register the Plugin

Import and register the plugin in your Payload config:

```typescript
import { buildConfig } from 'payload/config';
import { structuredDataGenerator } from '@sparrowengg/payloadcms-plugin-structured-data-generator';
import { fieldNameMappings } from './config/structuredDataGenerator/fieldNameMappings';

export default buildConfig({
  plugins: [
    structuredDataGenerator({
      fieldName: 'structuredData',
      fieldPath: 'meta.structuredData',
      apiUrl: process.env.NEXT_PUBLIC_AI_STRUCTURED_DATA_API ?? '',
      fieldNameMappings: fieldNameMappings,
      org: 'SparrowGenie', // Use your product
      logoUrl: `${process.env.NEXT_PUBLIC_IMAGE_BASE_URL}/meta/sparrowgenie-logo.svg`, // Use your product logo
    }),
  ],
  // ... rest of your config
});
```

### 3. Enable the Widget

Add structuredData field in required collections/globals.

```typescript
        {
        // Existing code
          name: 'meta',
          label: 'SEO',
          fields: [
            MetaTitleField({
              hasGenerateFn: true,
            }),
            MetaDescriptionField({}),
            // Add this field
            {
              name: 'structuredData',
              type: 'json',
            },
          ]
        }
```

### 4. Regenerate Payload's Importmap

```bash
pnpm payload generate:importmap
```

### 5. Injecting the Structured Data in Frontend code

Add the Structured Data reusable component in components folder.

```typescript
import Script from 'next/script';

export function StructuredData({ jsonLd }) {
  if (!jsonLd) {
    return null;
  }
  return (
    <Script
      id="schema-structured-data"
      type="application/ld+json"
      dangerouslySetInnerHTML={{
        __html: JSON.stringify(jsonLd),
      }}
      strategy="lazyOnload"
    />
  );
}
```

In whichever page you want this, in the page.jsx file use this component and pass the structured data from Payload CMS to it.

```typescript
import { StructuredData } from '@/components/scripts/structured-data';
/// const cmsData = fetch cms page data
<StructuredData jsonLd={cmsData.seo.structuredData} />
```

### 6. Using the Widget

- Widget will appear below the structured data field on frontend.
- Start interlinking using the button.
- Use the 'Verify' link to copy paste and verify the structured data.