Integrate the TrendSync plugin across modern web stacks.
This guide is based on the current project implementation: the official loader script, the API-key metadata endpoint, the indexing webhook, and the WordPress plugin settings already shipped in this codebase.
React
Browser loader for SPAs and client-heavy React applications.
JavaScript Websites
Fastest drop-in option for plain HTML sites and static pages.
PHP
Server-rendered metadata for custom PHP sites and frameworks.
WordPress
Official plugin with settings, verification, caching, and status reporting.
Next.js
Use either the loader script or fetch metadata in the App Router.
How TrendSync Works
Every connector in this project follows the same runtime contract, so once the credentials are ready you can plug it into almost any stack.
TrendSync stores the selected metadata recommendation for a client.
Your site calls `GET /api/plugin/metadata` with the `X-Api-Key` header.
The response includes title, description, keywords, Open Graph, Twitter Card, structured data, and canonical URL.
After successful injection, the connector can notify TrendSync with `POST /api/indexing/metadata-injected`.
Before You Start
Official Loader Script
Use this when you want the browser to fetch metadata and inject it automatically. This is the same contract exposed by `backend/controller/pluginController.js`.
<!-- Place this inside <head> -->
<script
async
src="https://api.yourdomain.com/api/plugin/trendsync.min.js"
data-api-key="YOUR_API_KEY"
data-auto-inject="true"
></script>Current live endpoint contract: `GET /api/plugin/metadata` with `X-Api-Key`, followed by optional `POST /api/indexing/metadata-injected`.
Optional Injection Reporting
After metadata is applied, your connector can notify TrendSync so automatic indexing workflows can continue.
await fetch("https://api.yourdomain.com/api/indexing/metadata-injected", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": "YOUR_API_KEY",
},
body: JSON.stringify({
url: window.location.href,
metadataType: "full",
}),
});Legacy Connector Flow
TrendSync still ships an older compatibility path in the backend. New integrations should use `trendsync.min.js` plus `X-Api-Key`, but existing installs may still rely on the legacy client-ID flow.
`GET /api/plugin/loader.js` returns the older browser loader.
That loader expects a `key` query param for `clientId` and an optional `token` query param.
It fetches `GET /api/plugin/seo-data/:clientId?path=...` instead of `/api/plugin/metadata`.
It is still present in the backend for backward compatibility, but the API-key based `trendsync.min.js` flow is the preferred integration path.
<!-- Legacy loader -->
<script
src="https://api.yourdomain.com/api/plugin/loader.js?key=CLIENT_ID&token=OPTIONAL_BEARER_TOKEN"
async
></script>React Applications
Best for single-page apps, Vite projects, and client-side React sites where the browser can inject SEO tags after hydration.
<head> updates.import { useEffect } from "react";
export function TrendSyncLoader() {
useEffect(() => {
const script = document.createElement("script");
script.src = "https://api.yourdomain.com/api/plugin/trendsync.min.js";
script.async = true;
script.dataset.apiKey = process.env.REACT_APP_TRENDSYNC_API_KEY || "";
script.dataset.autoInject = "true";
document.head.appendChild(script);
return () => {
document.head.removeChild(script);
};
}, []);
return null;
}// App.tsx
import { TrendSyncLoader } from "./TrendSyncLoader";
export default function App() {
return (
<>
<TrendSyncLoader />
{/* your routes */}
</>
);
}JavaScript-Based Websites
Best for plain HTML, marketing sites, static exports, legacy websites, or any site where you can edit the global document head.
Setup Steps
<head>.</head> tag.Snippet
<!-- Place this inside <head> -->
<script
async
src="https://api.yourdomain.com/api/plugin/trendsync.min.js"
data-api-key="YOUR_API_KEY"
data-auto-inject="true"
></script>PHP-Based Websites
Best for Laravel, Symfony, CodeIgniter, custom PHP sites, or any server-rendered application where metadata should be produced before HTML reaches the browser.
<?php
$backendUrl = 'https://api.yourdomain.com';
$apiKey = 'YOUR_API_KEY';
function fetchTrendSyncMetadata(string $backendUrl, string $apiKey): ?array {
$ch = curl_init($backendUrl . '/api/plugin/metadata');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'X-Api-Key: ' . $apiKey,
],
CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status < 200 || $status >= 300 || !$response) {
return null;
}
return json_decode($response, true);
}
$data = fetchTrendSyncMetadata($backendUrl, $apiKey);
$meta = $data['metadata'] ?? null;
?>
<?php if ($meta): ?>
<title><?= htmlspecialchars($meta['title'] ?? '') ?></title>
<meta name="description" content="<?= htmlspecialchars($meta['description'] ?? '') ?>">
<meta name="keywords" content="<?= htmlspecialchars(implode(', ', $meta['keywords'] ?? [])) ?>">
<link rel="canonical" href="<?= htmlspecialchars($meta['canonical'] ?? '') ?>">
<?php endif; ?>WordPress
This project already ships an official WordPress plugin that adds an admin settings page, verifies the connection, caches metadata for each path, injects SEO tags in `wp_head`, and reports plugin status back to TrendSync.
WordPress plugin settings
api_key -> TrendSync API key
client_id -> Stored by the plugin UI, but current metadata fetch uses the API key
backend_url -> https://api.yourdomain.com
website_url -> https://your-wordpress-site.com
auto_inject -> enabled by defaultNext.js Applications
Next.js supports two good integration styles: use the official browser loader for fast setup, or fetch metadata server-side inside the App Router for stronger SSR control.
Option A: Loader Script
Use this when you want the same behavior as a normal JavaScript integration.
import Script from "next/script";
export function TrendSyncScript() {
return (
<Script
id="trendsync-loader"
src="https://api.yourdomain.com/api/plugin/trendsync.min.js"
strategy="afterInteractive"
data-api-key={process.env.NEXT_PUBLIC_TRENDSYNC_API_KEY}
data-auto-inject="true"
/>
);
}Option B: Server Metadata
Use this when you want metadata resolved during rendering with App Router APIs.
const BACKEND_URL = process.env.TRENDSYNC_BACKEND_URL!;
const API_KEY = process.env.TRENDSYNC_API_KEY!;
async function getTrendSyncMetadata() {
const response = await fetch(`${BACKEND_URL}/api/plugin/metadata`, {
headers: {
"X-Api-Key": API_KEY,
Accept: "application/json",
},
next: { revalidate: 600 },
});
if (!response.ok) {
return null;
}
return response.json();
}
export async function generateMetadata() {
const data = await getTrendSyncMetadata();
const metadata = data?.metadata;
if (!metadata) {
return {};
}
return {
title: metadata.title,
description: metadata.description,
keywords: metadata.keywords,
openGraph: metadata.openGraph,
twitter: metadata.twitterCard,
alternates: {
canonical: metadata.canonical,
},
};
}