react-client-seo 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,6 +11,7 @@ A lightweight, production-ready client-side SEO renderer for React and Vite appl
11
11
  - ✅ **Component & Hook APIs** - Use `<Seo />` component or `useSeo()` hook
12
12
  - ✅ **Auto-updates** - Automatically creates/updates tags, avoids duplicates
13
13
  - ✅ **Comprehensive** - Supports title, meta tags, Open Graph, Twitter Cards, JSON-LD, and custom meta tags
14
+ - ✅ **Script Injection** - Built-in support for Google Analytics, Tag Manager, and custom scripts
14
15
 
15
16
  ## Installation
16
17
 
@@ -36,7 +37,7 @@ pnpm add react-client-seo
36
37
  ### Component API
37
38
 
38
39
  ```tsx
39
- import { Seo } from 'react-client-seo';
40
+ import { Seo } from "react-client-seo";
40
41
 
41
42
  function App() {
42
43
  return (
@@ -44,7 +45,9 @@ function App() {
44
45
  <Seo
45
46
  title="My Page Title"
46
47
  description="This is a great page about React SEO"
47
- keywords={['react', 'seo', 'meta tags']}
48
+ keywords={["react", "seo", "meta tags"]}
49
+ author="John Doe"
50
+ robots="index, follow"
48
51
  canonical="https://example.com/page"
49
52
  />
50
53
  <div>Your content here</div>
@@ -56,17 +59,17 @@ function App() {
56
59
  ### Hook API
57
60
 
58
61
  ```tsx
59
- import { useSeo } from 'react-client-seo';
60
- import { useEffect } from 'react';
62
+ import { useSeo } from "react-client-seo";
63
+ import { useEffect } from "react";
61
64
 
62
65
  function MyComponent() {
63
66
  const { updateSeo } = useSeo();
64
67
 
65
68
  useEffect(() => {
66
69
  updateSeo({
67
- title: 'My Page Title',
68
- description: 'Page description',
69
- keywords: 'react, seo',
70
+ title: "My Page Title",
71
+ description: "Page description",
72
+ keywords: "react, seo",
70
73
  });
71
74
  }, []);
72
75
 
@@ -83,6 +86,87 @@ function MyComponent() {
83
86
  title="Home Page"
84
87
  description="Welcome to our website"
85
88
  keywords="home, welcome, website"
89
+ author="John Doe"
90
+ robots="index, follow"
91
+ language="en"
92
+ viewport="width=device-width, initial-scale=1"
93
+ />
94
+ ```
95
+
96
+ ### Geo Tags
97
+
98
+ ```tsx
99
+ <Seo
100
+ title="Location Page"
101
+ description="Our location"
102
+ geoRegion="US-NY"
103
+ geoPlacename="New York"
104
+ geoPosition="40.7128;-74.0060"
105
+ icbm="40.7128, -74.0060"
106
+ />
107
+ ```
108
+
109
+ ### Google Analytics
110
+
111
+ ```tsx
112
+ <Seo
113
+ title="My Page"
114
+ description="Page description"
115
+ googleAnalyticsId="G-XXXXXXXXXX"
116
+ />
117
+ ```
118
+
119
+ ### Google Tag Manager
120
+
121
+ ```tsx
122
+ <Seo
123
+ title="My Page"
124
+ description="Page description"
125
+ googleTagManagerId="GTM-XXXXXXX"
126
+ />
127
+ ```
128
+
129
+ ### Custom Scripts
130
+
131
+ ```tsx
132
+ // External script
133
+ <Seo
134
+ title="My Page"
135
+ customScripts={[
136
+ {
137
+ src: "https://example.com/script.js",
138
+ id: "my-script",
139
+ async: true,
140
+ },
141
+ ]}
142
+ />
143
+
144
+ // Inline script
145
+ <Seo
146
+ title="My Page"
147
+ customScripts={[
148
+ {
149
+ content: "console.log('Hello from inline script');",
150
+ id: "inline-script",
151
+ },
152
+ ]}
153
+ />
154
+
155
+ // Multiple scripts with different strategies
156
+ <Seo
157
+ title="My Page"
158
+ customScripts={[
159
+ {
160
+ src: "https://example.com/async-script.js",
161
+ id: "async-script",
162
+ strategy: "async",
163
+ },
164
+ {
165
+ src: "https://example.com/defer-script.js",
166
+ id: "defer-script",
167
+ strategy: "defer",
168
+ },
169
+ ]}
86
170
  />
87
171
  ```
88
172
 
@@ -123,14 +207,14 @@ function MyComponent() {
123
207
  jsonLd={{
124
208
  "@context": "https://schema.org",
125
209
  "@type": "Product",
126
- "name": "Amazing Product",
127
- "description": "This is an amazing product",
128
- "image": "https://example.com/product.jpg",
129
- "offers": {
210
+ name: "Amazing Product",
211
+ description: "This is an amazing product",
212
+ image: "https://example.com/product.jpg",
213
+ offers: {
130
214
  "@type": "Offer",
131
- "price": "99.99",
132
- "priceCurrency": "USD"
133
- }
215
+ price: "99.99",
216
+ priceCurrency: "USD",
217
+ },
134
218
  }}
135
219
  />
136
220
  ```
@@ -169,7 +253,7 @@ function MyComponent() {
169
253
  ### Complete Example
170
254
 
171
255
  ```tsx
172
- import { Seo } from 'react-client-seo';
256
+ import { Seo } from "react-client-seo";
173
257
 
174
258
  function ProductPage({ product }) {
175
259
  return (
@@ -189,19 +273,17 @@ function ProductPage({ product }) {
189
273
  jsonLd={{
190
274
  "@context": "https://schema.org",
191
275
  "@type": "Product",
192
- "name": product.name,
193
- "description": product.description,
194
- "image": product.image,
195
- "offers": {
276
+ name: product.name,
277
+ description: product.description,
278
+ image: product.image,
279
+ offers: {
196
280
  "@type": "Offer",
197
- "price": product.price,
198
- "priceCurrency": "USD",
199
- "availability": "https://schema.org/InStock"
200
- }
281
+ price: product.price,
282
+ priceCurrency: "USD",
283
+ availability: "https://schema.org/InStock",
284
+ },
201
285
  }}
202
- customMeta={[
203
- { name: "robots", content: "index, follow" },
204
- ]}
286
+ customMeta={[{ name: "robots", content: "index, follow" }]}
205
287
  />
206
288
  <div>
207
289
  <h1>{product.name}</h1>
@@ -216,30 +298,51 @@ function ProductPage({ product }) {
216
298
 
217
299
  ### `<Seo />` Component Props
218
300
 
219
- | Prop | Type | Description |
220
- |------|------|-------------|
221
- | `title` | `string` | Page title |
222
- | `description` | `string` | Meta description |
223
- | `keywords` | `string \| string[]` | Meta keywords (comma-separated string or array) |
224
- | `canonical` | `string` | Canonical URL |
225
- | `ogImage` | `string` | Open Graph image URL |
226
- | `ogType` | `string` | Open Graph type (e.g., "article", "website") |
227
- | `ogUrl` | `string` | Open Graph URL |
228
- | `ogTitle` | `string` | Open Graph title (defaults to `title`) |
229
- | `ogDescription` | `string` | Open Graph description (defaults to `description`) |
230
- | `ogSiteName` | `string` | Open Graph site name |
231
- | `ogLocale` | `string` | Open Graph locale |
232
- | `twitterCard` | `'summary' \| 'summary_large_image' \| 'app' \| 'player'` | Twitter Card type |
233
- | `twitterSite` | `string` | Twitter site handle |
234
- | `twitterCreator` | `string` | Twitter creator handle |
235
- | `twitterTitle` | `string` | Twitter title (defaults to `title`) |
236
- | `twitterDescription` | `string` | Twitter description (defaults to `description`) |
237
- | `twitterImage` | `string` | Twitter image URL |
238
- | `twitterImageAlt` | `string` | Twitter image alt text |
239
- | `jsonLd` | `object \| object[]` | JSON-LD structured data |
240
- | `customMeta` | `CustomMeta[]` | Custom meta tags |
241
- | `openGraph` | `OpenGraphMeta` | Additional Open Graph properties |
242
- | `twitter` | `TwitterCardMeta` | Additional Twitter Card properties |
301
+ | Prop | Type | Description |
302
+ | -------------------------- | --------------------------------------------------------- | ----------------------------------------------------------- |
303
+ | `title` | `string` | Page title |
304
+ | `description` | `string` | Meta description |
305
+ | `keywords` | `string \| string[]` | Meta keywords (comma-separated string or array) |
306
+ | `author` | `string` | Meta author |
307
+ | `robots` | `string` | Meta robots (e.g., "index, follow", "noindex, nofollow") |
308
+ | `language` | `string` | Meta language/Content-Language |
309
+ | `viewport` | `string` | Meta viewport (e.g., "width=device-width, initial-scale=1") |
310
+ | `generator` | `string` | Meta generator |
311
+ | `revisitAfter` | `string` | Meta revisit-after (e.g., "7 days") |
312
+ | `rating` | `string` | Meta rating |
313
+ | `distribution` | `string` | Meta distribution |
314
+ | `copyright` | `string` | Meta copyright |
315
+ | `themeColor` | `string` | Meta theme-color |
316
+ | `referrer` | `string` | Meta referrer |
317
+ | `formatDetection` | `string` | Meta format-detection (mobile) |
318
+ | `mobileWebAppCapable` | `string` | Meta mobile-web-app-capable |
319
+ | `appleMobileWebAppCapable` | `string` | Meta apple-mobile-web-app-capable |
320
+ | `geoRegion` | `string` | Geo region (e.g., "US-NY") |
321
+ | `geoPlacename` | `string` | Geo placename |
322
+ | `geoPosition` | `string` | Geo position (e.g., "latitude;longitude") |
323
+ | `icbm` | `string` | ICBM coordinates (e.g., "latitude, longitude") |
324
+ | `canonical` | `string` | Canonical URL |
325
+ | `ogImage` | `string` | Open Graph image URL |
326
+ | `ogType` | `string` | Open Graph type (e.g., "article", "website") |
327
+ | `ogUrl` | `string` | Open Graph URL |
328
+ | `ogTitle` | `string` | Open Graph title (defaults to `title`) |
329
+ | `ogDescription` | `string` | Open Graph description (defaults to `description`) |
330
+ | `ogSiteName` | `string` | Open Graph site name |
331
+ | `ogLocale` | `string` | Open Graph locale |
332
+ | `twitterCard` | `'summary' \| 'summary_large_image' \| 'app' \| 'player'` | Twitter Card type |
333
+ | `twitterSite` | `string` | Twitter site handle |
334
+ | `twitterCreator` | `string` | Twitter creator handle |
335
+ | `twitterTitle` | `string` | Twitter title (defaults to `title`) |
336
+ | `twitterDescription` | `string` | Twitter description (defaults to `description`) |
337
+ | `twitterImage` | `string` | Twitter image URL |
338
+ | `twitterImageAlt` | `string` | Twitter image alt text |
339
+ | `jsonLd` | `object \| object[]` | JSON-LD structured data |
340
+ | `customMeta` | `CustomMeta[]` | Custom meta tags |
341
+ | `openGraph` | `OpenGraphMeta` | Additional Open Graph properties |
342
+ | `twitter` | `TwitterCardMeta` | Additional Twitter Card properties |
343
+ | `googleAnalyticsId` | `string` | Google Analytics ID (gtag.js) |
344
+ | `googleTagManagerId` | `string` | Google Tag Manager ID |
345
+ | `customScripts` | `CustomScript[]` | Custom scripts to inject (external or inline) |
243
346
 
244
347
  ### `useSeo()` Hook
245
348
 
@@ -253,7 +356,14 @@ Returns an object with:
253
356
  Full TypeScript support is included. Import types as needed:
254
357
 
255
358
  ```tsx
256
- import type { SeoProps, OpenGraphMeta, TwitterCardMeta, CustomMeta, JsonLd } from 'react-client-seo';
359
+ import type {
360
+ SeoProps,
361
+ OpenGraphMeta,
362
+ TwitterCardMeta,
363
+ CustomMeta,
364
+ CustomScript,
365
+ JsonLd,
366
+ } from "react-client-seo";
257
367
  ```
258
368
 
259
369
  ## How It Works
@@ -264,19 +374,11 @@ import type { SeoProps, OpenGraphMeta, TwitterCardMeta, CustomMeta, JsonLd } fro
264
374
  - Cleans up JSON-LD scripts on unmount (component API)
265
375
  - Works entirely client-side - no SSR required
266
376
 
267
- ## Publishing to NPM
377
+ ## Author
268
378
 
269
- 1. Update version in `package.json`
270
- 2. Build the package:
271
- ```bash
272
- npm run build
273
- ```
274
- 3. Publish:
275
- ```bash
276
- npm publish
277
- ```
278
-
279
- The `prepare` script automatically runs before publishing, ensuring the package is built.
379
+ **Rainard Joseph**
380
+ I'm working as a Software Project Manager at [Odidor](https://odidor.app/), working on the ERP and IMS software products. I love coding.
381
+ Connect with on [LinkedIn](https://www.linkedin.com/in/rainard-joseph)
280
382
 
281
383
  ## License
282
384
 
@@ -285,4 +387,3 @@ MIT
285
387
  ## Contributing
286
388
 
287
389
  Contributions are welcome! Please feel free to submit a Pull Request.
288
-
package/dist/Seo.d.ts CHANGED
@@ -18,5 +18,5 @@ import { SeoProps } from './types';
18
18
  * />
19
19
  * ```
20
20
  */
21
- export declare function Seo({ title, description, keywords, canonical, ogImage, ogType, ogUrl, ogTitle, ogDescription, ogSiteName, ogLocale, twitterCard, twitterSite, twitterCreator, twitterTitle, twitterDescription, twitterImage, twitterImageAlt, jsonLd, customMeta, openGraph, twitter, }: SeoProps): null;
21
+ export declare function Seo({ title, description, keywords, author, robots, language, viewport, generator, revisitAfter, rating, distribution, copyright, themeColor, referrer, formatDetection, mobileWebAppCapable, appleMobileWebAppCapable, geoRegion, geoPlacename, geoPosition, icbm, canonical, ogImage, ogType, ogUrl, ogTitle, ogDescription, ogSiteName, ogLocale, twitterCard, twitterSite, twitterCreator, twitterTitle, twitterDescription, twitterImage, twitterImageAlt, jsonLd, customMeta, openGraph, twitter, googleAnalyticsId, googleTagManagerId, customScripts, }: SeoProps): null;
22
22
  //# sourceMappingURL=Seo.d.ts.map
package/dist/Seo.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Seo.d.ts","sourceRoot":"","sources":["../src/Seo.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAcxC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,GAAG,CAAC,EAClB,KAAK,EACL,WAAW,EACX,QAAQ,EACR,SAAS,EACT,OAAO,EACP,MAAM,EACN,KAAK,EACL,OAAO,EACP,aAAa,EACb,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,MAAM,EACN,UAAU,EACV,SAAS,EACT,OAAO,GACR,EAAE,QAAQ,QAgIV"}
1
+ {"version":3,"file":"Seo.d.ts","sourceRoot":"","sources":["../src/Seo.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAiBxC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,GAAG,CAAC,EAClB,KAAK,EACL,WAAW,EACX,QAAQ,EACR,MAAM,EACN,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,SAAS,EACT,UAAU,EACV,QAAQ,EACR,eAAe,EACf,mBAAmB,EACnB,wBAAwB,EACxB,SAAS,EACT,YAAY,EACZ,WAAW,EACX,IAAI,EACJ,SAAS,EACT,OAAO,EACP,MAAM,EACN,KAAK,EACL,OAAO,EACP,aAAa,EACb,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,MAAM,EACN,UAAU,EACV,SAAS,EACT,OAAO,EACP,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,GACd,EAAE,QAAQ,QAsQV"}
package/dist/index.cjs CHANGED
@@ -1,2 +1,13 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const W=require("react");function T(e,t){const i=`meta[${e}="${t}"]`;let n=document.querySelector(i);return n||(n=document.createElement("meta"),n.setAttribute(e,t),document.head.appendChild(n)),n}function c(e,t){if(!t)return;T("name",e).setAttribute("content",t)}function f(e,t){if(t==null||t==="")return;T("property",e).setAttribute("content",String(t))}function $(e){e&&(document.title=e)}function B(e){if(!e)return;let t=document.querySelector('link[rel="canonical"]');t||(t=document.createElement("link"),t.setAttribute("rel","canonical"),document.head.appendChild(t)),t.setAttribute("href",e)}function G(){const e=document.querySelector('link[rel="canonical"]');e&&e.remove()}function H(e){e&&(e.title&&f("og:title",e.title),e.description&&f("og:description",e.description),e.type&&f("og:type",e.type),e.url&&f("og:url",e.url),e.image&&f("og:image",e.image),e.imageWidth&&f("og:image:width",e.imageWidth),e.imageHeight&&f("og:image:height",e.imageHeight),e.imageAlt&&f("og:image:alt",e.imageAlt),e.siteName&&f("og:site_name",e.siteName),e.locale&&f("og:locale",e.locale),Object.keys(e).forEach(t=>{if(t.startsWith("og:")&&t!=="og:title"&&t!=="og:description"&&t!=="og:type"&&t!=="og:url"&&t!=="og:image"&&t!=="og:imageWidth"&&t!=="og:imageHeight"&&t!=="og:imageAlt"&&t!=="og:siteName"&&t!=="og:locale"){const i=e[t];i!=null&&i!==""&&f(t,i)}}))}function L(e){e&&(e.card&&c("twitter:card",e.card),e.site&&c("twitter:site",e.site),e.creator&&c("twitter:creator",e.creator),e.title&&c("twitter:title",e.title),e.description&&c("twitter:description",e.description),e.image&&c("twitter:image",e.image),e.imageAlt&&c("twitter:image:alt",e.imageAlt),Object.keys(e).forEach(t=>{if(t.startsWith("twitter:")&&t!=="twitter:card"&&t!=="twitter:site"&&t!=="twitter:creator"&&t!=="twitter:title"&&t!=="twitter:description"&&t!=="twitter:image"&&t!=="twitter:imageAlt"){const i=e[t];i!=null&&i!==""&&c(t,String(i))}}))}function x(e){!e||!Array.isArray(e)||e.forEach(t=>{if(!t.content)return;let i=null;if(t.name)i=T("name",t.name);else if(t.property)i=T("property",t.property);else if(t.httpEquiv){const n=`meta[http-equiv="${t.httpEquiv}"]`;i=document.querySelector(n),i||(i=document.createElement("meta"),i.setAttribute("http-equiv",t.httpEquiv),document.head.appendChild(i))}else if(t.charset){let n=document.querySelector("meta[charset]");n||(n=document.createElement("meta"),n.setAttribute("charset",t.charset),document.head.insertBefore(n,document.head.firstChild));return}i&&i.setAttribute("content",t.content)})}function M(e,t){const i=document.createElement("script");i.type="application/ld+json";{i.id=t;const n=document.getElementById(t);n&&n.remove()}return i.textContent=JSON.stringify(e),document.head.appendChild(i),()=>{i.remove()}}function K(e){const t=document.getElementById(e);t&&t.getAttribute("type")==="application/ld+json"&&t.remove()}function P(e){return e?Array.isArray(e)?e.join(", "):e:""}const z="react-client-seo-jsonld";function F({title:e,description:t,keywords:i,canonical:n,ogImage:r,ogType:C,ogUrl:u,ogTitle:d,ogDescription:m,ogSiteName:p,ogLocale:h,twitterCard:g,twitterSite:A,twitterCreator:b,twitterTitle:S,twitterDescription:v,twitterImage:E,twitterImageAlt:y,jsonLd:j,customMeta:O,openGraph:N,twitter:D}){return W.useEffect(()=>{e&&$(e),t&&c("description",t);const J=P(i);J&&c("keywords",J),n&&B(n);const o={...N};(d||e)&&(o.title=d||e),(m||t)&&(o.description=m||t),C&&(o.type=C),(u||n)&&(o.url=u||n),r&&(o.image=r),p&&(o.siteName=p),h&&(o.locale=h),Object.keys(o).length>0&&H(o);const a={...D};g&&(a.card=g),A&&(a.site=A),b&&(a.creator=b),(S||e)&&(a.title=S||e),(v||t)&&(a.description=v||t),(E||r)&&(a.image=E||r),y&&(a.imageAlt=y),Object.keys(a).length>0&&L(a),O&&x(O);let q=null;return j&&(q=M(j,z)),()=>{q&&q()}},[e,t,i,n,r,C,u,d,m,p,h,g,A,b,S,v,E,y,j,O,N,D]),null}const _="react-client-seo-jsonld";function Q(){const e=W.useCallback(i=>{const{title:n,description:r,keywords:C,canonical:u,ogImage:d,ogType:m,ogUrl:p,ogTitle:h,ogDescription:g,ogSiteName:A,ogLocale:b,twitterCard:S,twitterSite:v,twitterCreator:E,twitterTitle:y,twitterDescription:j,twitterImage:O,twitterImageAlt:N,jsonLd:D,customMeta:J,openGraph:o,twitter:a}=i;n&&$(n),r&&c("description",r);const q=P(C);q&&c("keywords",q),u&&B(u);const l={...o};(h||n)&&(l.title=h||n),(g||r)&&(l.description=g||r),m&&(l.type=m),(p||u)&&(l.url=p||u),d&&(l.image=d),A&&(l.siteName=A),b&&(l.locale=b),Object.keys(l).length>0&&H(l);const s={...a};S&&(s.card=S),v&&(s.site=v),E&&(s.creator=E),(y||n)&&(s.title=y||n),(j||r)&&(s.description=j||r),(O||d)&&(s.image=O||d),N&&(s.imageAlt=N),Object.keys(s).length>0&&L(s),J&&x(J),D&&M(D,_)},[]),t=W.useCallback(()=>{G(),K(_)},[]);return{updateSeo:e,clearSeo:t}}exports.Seo=F;exports.useSeo=Q;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const te=require("react");function k(e,t){const i=`meta[${e}="${t}"]`;let r=document.querySelector(i);return r||(r=document.createElement("meta"),r.setAttribute(e,t),document.head.appendChild(r)),r}function n(e,t){if(!t)return;k("name",e).setAttribute("content",t)}function l(e,t){if(t==null||t==="")return;k("property",e).setAttribute("content",String(t))}function ne(e){e&&(document.title=e)}function re(e){if(!e)return;let t=document.querySelector('link[rel="canonical"]');t||(t=document.createElement("link"),t.setAttribute("rel","canonical"),document.head.appendChild(t)),t.setAttribute("href",e)}function pe(){const e=document.querySelector('link[rel="canonical"]');e&&e.remove()}function ae(e){e&&(e.title&&l("og:title",e.title),e.description&&l("og:description",e.description),e.type&&l("og:type",e.type),e.url&&l("og:url",e.url),e.image&&l("og:image",e.image),e.imageWidth&&l("og:image:width",e.imageWidth),e.imageHeight&&l("og:image:height",e.imageHeight),e.imageAlt&&l("og:image:alt",e.imageAlt),e.siteName&&l("og:site_name",e.siteName),e.locale&&l("og:locale",e.locale),Object.keys(e).forEach(t=>{if(t.startsWith("og:")&&t!=="og:title"&&t!=="og:description"&&t!=="og:type"&&t!=="og:url"&&t!=="og:image"&&t!=="og:imageWidth"&&t!=="og:imageHeight"&&t!=="og:imageAlt"&&t!=="og:siteName"&&t!=="og:locale"){const i=e[t];i!=null&&i!==""&&l(t,i)}}))}function ce(e){e&&(e.card&&n("twitter:card",e.card),e.site&&n("twitter:site",e.site),e.creator&&n("twitter:creator",e.creator),e.title&&n("twitter:title",e.title),e.description&&n("twitter:description",e.description),e.image&&n("twitter:image",e.image),e.imageAlt&&n("twitter:image:alt",e.imageAlt),Object.keys(e).forEach(t=>{if(t.startsWith("twitter:")&&t!=="twitter:card"&&t!=="twitter:site"&&t!=="twitter:creator"&&t!=="twitter:title"&&t!=="twitter:description"&&t!=="twitter:image"&&t!=="twitter:imageAlt"){const i=e[t];i!=null&&i!==""&&n(t,String(i))}}))}function oe(e){!e||!Array.isArray(e)||e.forEach(t=>{if(!t.content)return;let i=null;if(t.name)i=k("name",t.name);else if(t.property)i=k("property",t.property);else if(t.httpEquiv){const r=`meta[http-equiv="${t.httpEquiv}"]`;i=document.querySelector(r),i||(i=document.createElement("meta"),i.setAttribute("http-equiv",t.httpEquiv),document.head.appendChild(i))}else if(t.charset){let r=document.querySelector("meta[charset]");r||(r=document.createElement("meta"),r.setAttribute("charset",t.charset),document.head.insertBefore(r,document.head.firstChild));return}i&&i.setAttribute("content",t.content)})}function fe(e,t){const i=document.createElement("script");i.type="application/ld+json";{i.id=t;const r=document.getElementById(t);r&&r.remove()}return i.textContent=JSON.stringify(e),document.head.appendChild(i),()=>{i.remove()}}function ge(e){const t=document.getElementById(e);t&&t.getAttribute("type")==="application/ld+json"&&t.remove()}function se(e){return e?Array.isArray(e)?e.join(", "):e:""}function y(e){const t=document.getElementById(e);t&&t.tagName==="SCRIPT"&&t.remove()}function le(e){const t="react-client-seo-ga",i="react-client-seo-ga-config";y(t),y(i);const r=document.createElement("script");r.id=t,r.async=!0,r.src=`https://www.googletagmanager.com/gtag/js?id=${e}`,document.head.appendChild(r);const a=document.createElement("script");return a.id=i,a.textContent=`
2
+ window.dataLayer = window.dataLayer || [];
3
+ function gtag(){dataLayer.push(arguments);}
4
+ gtag('js', new Date());
5
+ gtag('config', '${e}');
6
+ `,document.head.appendChild(a),()=>{y(t),y(i)}}function ue(e){const t="react-client-seo-gtm",i="react-client-seo-gtm-noscript";y(t);const r=document.getElementById(i);r&&r.remove();const a=document.createElement("script");a.id=t,a.textContent=`
7
+ (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
8
+ new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
9
+ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
10
+ 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
11
+ })(window,document,'script','dataLayer','${e}');
12
+ `,document.head.appendChild(a);const u=document.createElement("noscript");return u.id=i,u.innerHTML=`<iframe src="https://www.googletagmanager.com/ns.html?id=${e}" height="0" width="0" style="display:none;visibility:hidden"></iframe>`,document.head.appendChild(u),()=>{y(t);const d=document.getElementById(i);d&&d.remove()}}function de(e){if(!e.src&&!e.content)return console.warn("CustomScript must have either src or content"),()=>{};const t=e.id||`react-client-seo-custom-${Date.now()}`;e.id&&y(e.id);const i=document.createElement("script");return i.id=t,e.src&&(i.src=e.src),e.content&&(i.textContent=e.content),e.type?i.type=e.type:i.type="text/javascript",(e.strategy==="async"||e.async)&&(i.async=!0),(e.strategy==="defer"||e.defer)&&(i.defer=!0),document.head.appendChild(i),()=>{y(t)}}const he="react-client-seo-jsonld";function ye({title:e,description:t,keywords:i,author:r,robots:a,language:u,viewport:d,generator:v,revisitAfter:E,rating:w,distribution:b,copyright:S,themeColor:j,referrer:A,formatDetection:T,mobileWebAppCapable:O,appleMobileWebAppCapable:N,geoRegion:_,geoPlacename:C,geoPosition:D,icbm:I,canonical:m,ogImage:p,ogType:q,ogUrl:g,ogTitle:h,ogDescription:B,ogSiteName:G,ogLocale:L,twitterCard:$,twitterSite:x,twitterCreator:M,twitterTitle:J,twitterDescription:H,twitterImage:P,twitterImageAlt:R,jsonLd:W,customMeta:F,openGraph:V,twitter:X,googleAnalyticsId:K,googleTagManagerId:Y,customScripts:z}){return te.useEffect(()=>{e&&ne(e),t&&n("description",t);const Z=se(i);Z&&n("keywords",Z),r&&n("author",r),a&&n("robots",a),u&&(n("language",u),n("content-language",u)),d&&n("viewport",d),v&&n("generator",v),E&&n("revisit-after",E),w&&n("rating",w),b&&n("distribution",b),S&&n("copyright",S),j&&n("theme-color",j),A&&n("referrer",A),T&&n("format-detection",T),O&&n("mobile-web-app-capable",O),N&&n("apple-mobile-web-app-capable",N),_&&n("geo.region",_),C&&n("geo.placename",C),D&&n("geo.position",D),I&&n("ICBM",I),m&&re(m);const s={...V};(h||e)&&(s.title=h||e),(B||t)&&(s.description=B||t),q&&(s.type=q),(g||m)&&(s.url=g||m),p&&(s.image=p),G&&(s.siteName=G),L&&(s.locale=L),Object.keys(s).length>0&&ae(s);const c={...X};$&&(c.card=$),x&&(c.site=x),M&&(c.creator=M),(J||e)&&(c.title=J||e),(H||t)&&(c.description=H||t),(P||p)&&(c.image=P||p),R&&(c.imageAlt=R),Object.keys(c).length>0&&ce(c),F&&oe(F);let Q=null;W&&(Q=fe(W,he));let o=null;K&&(o=le(K));let f=null;Y&&(f=ue(Y));const U=[];return z&&Array.isArray(z)&&z.forEach(ee=>{const me=de(ee);U.push(me)}),()=>{Q&&Q(),o&&o(),f&&f(),U.forEach(ee=>ee())}},[e,t,i,r,a,u,d,v,E,w,b,S,j,A,T,O,N,_,C,D,I,m,p,q,g,h,B,G,L,$,x,M,J,H,P,R,W,F,V,X,K,Y,z]),null}const ie="react-client-seo-jsonld";function Ee(){const e=te.useCallback(i=>{const{title:r,description:a,keywords:u,author:d,robots:v,language:E,viewport:w,generator:b,revisitAfter:S,rating:j,distribution:A,copyright:T,themeColor:O,referrer:N,formatDetection:_,mobileWebAppCapable:C,appleMobileWebAppCapable:D,geoRegion:I,geoPlacename:m,geoPosition:p,icbm:q,canonical:g,ogImage:h,ogType:B,ogUrl:G,ogTitle:L,ogDescription:$,ogSiteName:x,ogLocale:M,twitterCard:J,twitterSite:H,twitterCreator:P,twitterTitle:R,twitterDescription:W,twitterImage:F,twitterImageAlt:V,jsonLd:X,customMeta:K,openGraph:Y,twitter:z,googleAnalyticsId:Z,googleTagManagerId:s,customScripts:c}=i;r&&ne(r),a&&n("description",a);const Q=se(u);Q&&n("keywords",Q),d&&n("author",d),v&&n("robots",v),E&&(n("language",E),n("content-language",E)),w&&n("viewport",w),b&&n("generator",b),S&&n("revisit-after",S),j&&n("rating",j),A&&n("distribution",A),T&&n("copyright",T),O&&n("theme-color",O),N&&n("referrer",N),_&&n("format-detection",_),C&&n("mobile-web-app-capable",C),D&&n("apple-mobile-web-app-capable",D),I&&n("geo.region",I),m&&n("geo.placename",m),p&&n("geo.position",p),q&&n("ICBM",q),g&&re(g);const o={...Y};(L||r)&&(o.title=L||r),($||a)&&(o.description=$||a),B&&(o.type=B),(G||g)&&(o.url=G||g),h&&(o.image=h),x&&(o.siteName=x),M&&(o.locale=M),Object.keys(o).length>0&&ae(o);const f={...z};J&&(f.card=J),H&&(f.site=H),P&&(f.creator=P),(R||r)&&(f.title=R||r),(W||a)&&(f.description=W||a),(F||h)&&(f.image=F||h),V&&(f.imageAlt=V),Object.keys(f).length>0&&ce(f),K&&oe(K),X&&fe(X,ie),Z&&le(Z),s&&ue(s),c&&Array.isArray(c)&&c.forEach(U=>{de(U)})},[]),t=te.useCallback(()=>{pe(),ge(ie)},[]);return{updateSeo:e,clearSeo:t}}exports.Seo=ye;exports.useSeo=Ee;
2
13
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/utils.ts","../src/Seo.tsx","../src/useSeo.ts"],"sourcesContent":["import type { CustomMeta, JsonLd, OpenGraphMeta, TwitterCardMeta } from './types';\r\n\r\n/**\r\n * Get or create a meta tag element\r\n */\r\nfunction getOrCreateMetaTag(attribute: 'name' | 'property', value: string): HTMLMetaElement {\r\n const selector = `meta[${attribute}=\"${value}\"]`;\r\n let element = document.querySelector<HTMLMetaElement>(selector);\r\n\r\n if (!element) {\r\n element = document.createElement('meta');\r\n element.setAttribute(attribute, value);\r\n document.head.appendChild(element);\r\n }\r\n\r\n return element;\r\n}\r\n\r\n/**\r\n * Set a meta tag by name\r\n */\r\nexport function setMetaTag(name: string, content: string): void {\r\n if (!content) return;\r\n\r\n const element = getOrCreateMetaTag('name', name);\r\n element.setAttribute('content', content);\r\n}\r\n\r\n/**\r\n * Set a meta tag by property (for Open Graph)\r\n */\r\nexport function setMetaProperty(property: string, content: string | number): void {\r\n if (content === undefined || content === null || content === '') return;\r\n\r\n const element = getOrCreateMetaTag('property', property);\r\n element.setAttribute('content', String(content));\r\n}\r\n\r\n/**\r\n * Set the page title\r\n */\r\nexport function setTitle(title: string): void {\r\n if (!title) return;\r\n document.title = title;\r\n}\r\n\r\n/**\r\n * Set canonical URL\r\n */\r\nexport function setCanonical(url: string): void {\r\n if (!url) return;\r\n\r\n let link = document.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\r\n if (!link) {\r\n link = document.createElement('link');\r\n link.setAttribute('rel', 'canonical');\r\n document.head.appendChild(link);\r\n }\r\n link.setAttribute('href', url);\r\n}\r\n\r\n/**\r\n * Remove canonical URL\r\n */\r\nexport function removeCanonical(): void {\r\n const link = document.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\r\n if (link) {\r\n link.remove();\r\n }\r\n}\r\n\r\n/**\r\n * Set Open Graph meta tags\r\n */\r\nexport function setOpenGraphTags(og: OpenGraphMeta): void {\r\n if (!og) return;\r\n\r\n // Standard Open Graph properties\r\n if (og.title) setMetaProperty('og:title', og.title);\r\n if (og.description) setMetaProperty('og:description', og.description);\r\n if (og.type) setMetaProperty('og:type', og.type);\r\n if (og.url) setMetaProperty('og:url', og.url);\r\n if (og.image) setMetaProperty('og:image', og.image);\r\n if (og.imageWidth) setMetaProperty('og:image:width', og.imageWidth);\r\n if (og.imageHeight) setMetaProperty('og:image:height', og.imageHeight);\r\n if (og.imageAlt) setMetaProperty('og:image:alt', og.imageAlt);\r\n if (og.siteName) setMetaProperty('og:site_name', og.siteName);\r\n if (og.locale) setMetaProperty('og:locale', og.locale);\r\n\r\n // Handle additional custom og:* properties\r\n Object.keys(og).forEach((key) => {\r\n if (key.startsWith('og:') && key !== 'og:title' && key !== 'og:description' && \r\n key !== 'og:type' && key !== 'og:url' && key !== 'og:image' && \r\n key !== 'og:imageWidth' && key !== 'og:imageHeight' && \r\n key !== 'og:imageAlt' && key !== 'og:siteName' && key !== 'og:locale') {\r\n const value = og[key as keyof OpenGraphMeta];\r\n if (value !== undefined && value !== null && value !== '') {\r\n setMetaProperty(key, value as string | number);\r\n }\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Set Twitter Card meta tags\r\n */\r\nexport function setTwitterCardTags(twitter: TwitterCardMeta): void {\r\n if (!twitter) return;\r\n\r\n if (twitter.card) setMetaTag('twitter:card', twitter.card);\r\n if (twitter.site) setMetaTag('twitter:site', twitter.site);\r\n if (twitter.creator) setMetaTag('twitter:creator', twitter.creator);\r\n if (twitter.title) setMetaTag('twitter:title', twitter.title);\r\n if (twitter.description) setMetaTag('twitter:description', twitter.description);\r\n if (twitter.image) setMetaTag('twitter:image', twitter.image);\r\n if (twitter.imageAlt) setMetaTag('twitter:image:alt', twitter.imageAlt);\r\n\r\n // Handle additional custom twitter:* properties\r\n Object.keys(twitter).forEach((key) => {\r\n if (key.startsWith('twitter:') && key !== 'twitter:card' && key !== 'twitter:site' && \r\n key !== 'twitter:creator' && key !== 'twitter:title' && \r\n key !== 'twitter:description' && key !== 'twitter:image' && \r\n key !== 'twitter:imageAlt') {\r\n const value = twitter[key as keyof TwitterCardMeta];\r\n if (value !== undefined && value !== null && value !== '') {\r\n setMetaTag(key, String(value));\r\n }\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Set custom meta tags\r\n */\r\nexport function setCustomMetaTags(customMeta: CustomMeta[]): void {\r\n if (!customMeta || !Array.isArray(customMeta)) return;\r\n\r\n customMeta.forEach((meta) => {\r\n if (!meta.content) return;\r\n\r\n let element: HTMLMetaElement | null = null;\r\n\r\n if (meta.name) {\r\n element = getOrCreateMetaTag('name', meta.name);\r\n } else if (meta.property) {\r\n element = getOrCreateMetaTag('property', meta.property);\r\n } else if (meta.httpEquiv) {\r\n const selector = `meta[http-equiv=\"${meta.httpEquiv}\"]`;\r\n element = document.querySelector<HTMLMetaElement>(selector);\r\n if (!element) {\r\n element = document.createElement('meta');\r\n element.setAttribute('http-equiv', meta.httpEquiv);\r\n document.head.appendChild(element);\r\n }\r\n } else if (meta.charset) {\r\n let charsetElement = document.querySelector<HTMLMetaElement>('meta[charset]');\r\n if (!charsetElement) {\r\n charsetElement = document.createElement('meta');\r\n charsetElement.setAttribute('charset', meta.charset);\r\n document.head.insertBefore(charsetElement, document.head.firstChild);\r\n }\r\n return;\r\n }\r\n\r\n if (element) {\r\n element.setAttribute('content', meta.content);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Inject JSON-LD structured data\r\n */\r\nexport function injectJsonLd(data: JsonLd, id?: string): () => void {\r\n const script = document.createElement('script');\r\n script.type = 'application/ld+json';\r\n if (id) {\r\n script.id = id;\r\n // Remove existing script with same id\r\n const existing = document.getElementById(id);\r\n if (existing) {\r\n existing.remove();\r\n }\r\n }\r\n script.textContent = JSON.stringify(data);\r\n document.head.appendChild(script);\r\n\r\n // Return cleanup function\r\n return () => {\r\n script.remove();\r\n };\r\n}\r\n\r\n/**\r\n * Remove JSON-LD script by id\r\n */\r\nexport function removeJsonLd(id: string): void {\r\n const script = document.getElementById(id);\r\n if (script && script.getAttribute('type') === 'application/ld+json') {\r\n script.remove();\r\n }\r\n}\r\n\r\n/**\r\n * Format keywords as string\r\n */\r\nexport function formatKeywords(keywords: string | string[] | undefined): string {\r\n if (!keywords) return '';\r\n if (Array.isArray(keywords)) {\r\n return keywords.join(', ');\r\n }\r\n return keywords;\r\n}\r\n\r\n","import { useEffect } from 'react';\r\nimport type { SeoProps } from './types';\r\nimport {\r\n setTitle,\r\n setMetaTag,\r\n setCanonical,\r\n setOpenGraphTags,\r\n setTwitterCardTags,\r\n setCustomMetaTags,\r\n injectJsonLd,\r\n formatKeywords,\r\n} from './utils';\r\n\r\nconst JSON_LD_ID = 'react-client-seo-jsonld';\r\n\r\n/**\r\n * SEO Component\r\n * \r\n * Renders and updates SEO meta tags in the document head.\r\n * Returns null (no UI rendering).\r\n * \r\n * @example\r\n * ```tsx\r\n * <Seo\r\n * title=\"My Page Title\"\r\n * description=\"Page description\"\r\n * keywords={['react', 'seo']}\r\n * canonical=\"https://example.com/page\"\r\n * ogImage=\"https://example.com/image.jpg\"\r\n * jsonLd={{ \"@context\": \"https://schema.org\", \"@type\": \"WebPage\" }}\r\n * />\r\n * ```\r\n */\r\nexport function Seo({\r\n title,\r\n description,\r\n keywords,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n}: SeoProps) {\r\n useEffect(() => {\r\n // Set title\r\n if (title) {\r\n setTitle(title);\r\n }\r\n\r\n // Set description\r\n if (description) {\r\n setMetaTag('description', description);\r\n }\r\n\r\n // Set keywords\r\n const keywordsStr = formatKeywords(keywords);\r\n if (keywordsStr) {\r\n setMetaTag('keywords', keywordsStr);\r\n }\r\n\r\n // Set canonical URL\r\n if (canonical) {\r\n setCanonical(canonical);\r\n }\r\n\r\n // Build Open Graph object\r\n const ogData: any = {\r\n ...openGraph,\r\n };\r\n\r\n if (ogTitle || title) {\r\n ogData.title = ogTitle || title;\r\n }\r\n if (ogDescription || description) {\r\n ogData.description = ogDescription || description;\r\n }\r\n if (ogType) {\r\n ogData.type = ogType;\r\n }\r\n if (ogUrl || canonical) {\r\n ogData.url = ogUrl || canonical;\r\n }\r\n if (ogImage) {\r\n ogData.image = ogImage;\r\n }\r\n if (ogSiteName) {\r\n ogData.siteName = ogSiteName;\r\n }\r\n if (ogLocale) {\r\n ogData.locale = ogLocale;\r\n }\r\n\r\n if (Object.keys(ogData).length > 0) {\r\n setOpenGraphTags(ogData);\r\n }\r\n\r\n // Build Twitter Card object\r\n const twitterData: any = {\r\n ...twitter,\r\n };\r\n\r\n if (twitterCard) {\r\n twitterData.card = twitterCard;\r\n }\r\n if (twitterSite) {\r\n twitterData.site = twitterSite;\r\n }\r\n if (twitterCreator) {\r\n twitterData.creator = twitterCreator;\r\n }\r\n if (twitterTitle || title) {\r\n twitterData.title = twitterTitle || title;\r\n }\r\n if (twitterDescription || description) {\r\n twitterData.description = twitterDescription || description;\r\n }\r\n if (twitterImage || ogImage) {\r\n twitterData.image = twitterImage || ogImage;\r\n }\r\n if (twitterImageAlt) {\r\n twitterData.imageAlt = twitterImageAlt;\r\n }\r\n\r\n if (Object.keys(twitterData).length > 0) {\r\n setTwitterCardTags(twitterData);\r\n }\r\n\r\n // Set custom meta tags\r\n if (customMeta) {\r\n setCustomMetaTags(customMeta);\r\n }\r\n\r\n // Inject JSON-LD\r\n let cleanupJsonLd: (() => void) | null = null;\r\n if (jsonLd) {\r\n cleanupJsonLd = injectJsonLd(jsonLd, JSON_LD_ID);\r\n }\r\n\r\n // Cleanup function\r\n return () => {\r\n if (cleanupJsonLd) {\r\n cleanupJsonLd();\r\n }\r\n };\r\n }, [\r\n title,\r\n description,\r\n keywords,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n ]);\r\n\r\n return null;\r\n}\r\n\r\n","import { useCallback } from 'react';\r\nimport type { SeoProps, UseSeoReturn } from './types';\r\nimport {\r\n setTitle,\r\n setMetaTag,\r\n setCanonical,\r\n setOpenGraphTags,\r\n setTwitterCardTags,\r\n setCustomMetaTags,\r\n injectJsonLd,\r\n formatKeywords,\r\n removeCanonical,\r\n removeJsonLd,\r\n} from './utils';\r\n\r\nconst JSON_LD_ID = 'react-client-seo-jsonld';\r\n\r\n/**\r\n * useSeo Hook\r\n * \r\n * Hook-based API for managing SEO meta tags.\r\n * \r\n * @example\r\n * ```tsx\r\n * function MyComponent() {\r\n * const { updateSeo } = useSeo();\r\n * \r\n * useEffect(() => {\r\n * updateSeo({\r\n * title: 'My Page',\r\n * description: 'Page description',\r\n * });\r\n * }, []);\r\n * \r\n * return <div>Content</div>;\r\n * }\r\n * ```\r\n */\r\nexport function useSeo(): UseSeoReturn {\r\n const updateSeo = useCallback((props: SeoProps) => {\r\n const {\r\n title,\r\n description,\r\n keywords,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n } = props;\r\n\r\n // Set title\r\n if (title) {\r\n setTitle(title);\r\n }\r\n\r\n // Set description\r\n if (description) {\r\n setMetaTag('description', description);\r\n }\r\n\r\n // Set keywords\r\n const keywordsStr = formatKeywords(keywords);\r\n if (keywordsStr) {\r\n setMetaTag('keywords', keywordsStr);\r\n }\r\n\r\n // Set canonical URL\r\n if (canonical) {\r\n setCanonical(canonical);\r\n }\r\n\r\n // Build Open Graph object\r\n const ogData: any = {\r\n ...openGraph,\r\n };\r\n\r\n if (ogTitle || title) {\r\n ogData.title = ogTitle || title;\r\n }\r\n if (ogDescription || description) {\r\n ogData.description = ogDescription || description;\r\n }\r\n if (ogType) {\r\n ogData.type = ogType;\r\n }\r\n if (ogUrl || canonical) {\r\n ogData.url = ogUrl || canonical;\r\n }\r\n if (ogImage) {\r\n ogData.image = ogImage;\r\n }\r\n if (ogSiteName) {\r\n ogData.siteName = ogSiteName;\r\n }\r\n if (ogLocale) {\r\n ogData.locale = ogLocale;\r\n }\r\n\r\n if (Object.keys(ogData).length > 0) {\r\n setOpenGraphTags(ogData);\r\n }\r\n\r\n // Build Twitter Card object\r\n const twitterData: any = {\r\n ...twitter,\r\n };\r\n\r\n if (twitterCard) {\r\n twitterData.card = twitterCard;\r\n }\r\n if (twitterSite) {\r\n twitterData.site = twitterSite;\r\n }\r\n if (twitterCreator) {\r\n twitterData.creator = twitterCreator;\r\n }\r\n if (twitterTitle || title) {\r\n twitterData.title = twitterTitle || title;\r\n }\r\n if (twitterDescription || description) {\r\n twitterData.description = twitterDescription || description;\r\n }\r\n if (twitterImage || ogImage) {\r\n twitterData.image = twitterImage || ogImage;\r\n }\r\n if (twitterImageAlt) {\r\n twitterData.imageAlt = twitterImageAlt;\r\n }\r\n\r\n if (Object.keys(twitterData).length > 0) {\r\n setTwitterCardTags(twitterData);\r\n }\r\n\r\n // Set custom meta tags\r\n if (customMeta) {\r\n setCustomMetaTags(customMeta);\r\n }\r\n\r\n // Inject JSON-LD\r\n if (jsonLd) {\r\n injectJsonLd(jsonLd, JSON_LD_ID);\r\n }\r\n }, []);\r\n\r\n const clearSeo = useCallback(() => {\r\n // Note: We don't clear title, description, keywords as they might be set by other means\r\n // Only clear what we manage\r\n removeCanonical();\r\n removeJsonLd(JSON_LD_ID);\r\n }, []);\r\n\r\n return {\r\n updateSeo,\r\n clearSeo,\r\n };\r\n}\r\n\r\n"],"names":["getOrCreateMetaTag","attribute","value","selector","element","setMetaTag","name","content","setMetaProperty","property","setTitle","title","setCanonical","url","link","removeCanonical","setOpenGraphTags","og","key","setTwitterCardTags","twitter","setCustomMetaTags","customMeta","meta","charsetElement","injectJsonLd","data","id","script","existing","removeJsonLd","formatKeywords","keywords","JSON_LD_ID","Seo","description","canonical","ogImage","ogType","ogUrl","ogTitle","ogDescription","ogSiteName","ogLocale","twitterCard","twitterSite","twitterCreator","twitterTitle","twitterDescription","twitterImage","twitterImageAlt","jsonLd","openGraph","useEffect","keywordsStr","ogData","twitterData","cleanupJsonLd","useSeo","updateSeo","useCallback","props","clearSeo"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils.ts","../src/Seo.tsx","../src/useSeo.ts"],"sourcesContent":["import type { CustomMeta, CustomScript, JsonLd, OpenGraphMeta, TwitterCardMeta } from './types';\r\n\r\n/**\r\n * Get or create a meta tag element\r\n */\r\nfunction getOrCreateMetaTag(attribute: 'name' | 'property', value: string): HTMLMetaElement {\r\n const selector = `meta[${attribute}=\"${value}\"]`;\r\n let element = document.querySelector<HTMLMetaElement>(selector);\r\n\r\n if (!element) {\r\n element = document.createElement('meta');\r\n element.setAttribute(attribute, value);\r\n document.head.appendChild(element);\r\n }\r\n\r\n return element;\r\n}\r\n\r\n/**\r\n * Set a meta tag by name\r\n */\r\nexport function setMetaTag(name: string, content: string): void {\r\n if (!content) return;\r\n\r\n const element = getOrCreateMetaTag('name', name);\r\n element.setAttribute('content', content);\r\n}\r\n\r\n/**\r\n * Set a meta tag by property (for Open Graph)\r\n */\r\nexport function setMetaProperty(property: string, content: string | number): void {\r\n if (content === undefined || content === null || content === '') return;\r\n\r\n const element = getOrCreateMetaTag('property', property);\r\n element.setAttribute('content', String(content));\r\n}\r\n\r\n/**\r\n * Set the page title\r\n */\r\nexport function setTitle(title: string): void {\r\n if (!title) return;\r\n document.title = title;\r\n}\r\n\r\n/**\r\n * Set canonical URL\r\n */\r\nexport function setCanonical(url: string): void {\r\n if (!url) return;\r\n\r\n let link = document.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\r\n if (!link) {\r\n link = document.createElement('link');\r\n link.setAttribute('rel', 'canonical');\r\n document.head.appendChild(link);\r\n }\r\n link.setAttribute('href', url);\r\n}\r\n\r\n/**\r\n * Remove canonical URL\r\n */\r\nexport function removeCanonical(): void {\r\n const link = document.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\r\n if (link) {\r\n link.remove();\r\n }\r\n}\r\n\r\n/**\r\n * Set Open Graph meta tags\r\n */\r\nexport function setOpenGraphTags(og: OpenGraphMeta): void {\r\n if (!og) return;\r\n\r\n // Standard Open Graph properties\r\n if (og.title) setMetaProperty('og:title', og.title);\r\n if (og.description) setMetaProperty('og:description', og.description);\r\n if (og.type) setMetaProperty('og:type', og.type);\r\n if (og.url) setMetaProperty('og:url', og.url);\r\n if (og.image) setMetaProperty('og:image', og.image);\r\n if (og.imageWidth) setMetaProperty('og:image:width', og.imageWidth);\r\n if (og.imageHeight) setMetaProperty('og:image:height', og.imageHeight);\r\n if (og.imageAlt) setMetaProperty('og:image:alt', og.imageAlt);\r\n if (og.siteName) setMetaProperty('og:site_name', og.siteName);\r\n if (og.locale) setMetaProperty('og:locale', og.locale);\r\n\r\n // Handle additional custom og:* properties\r\n Object.keys(og).forEach((key) => {\r\n if (key.startsWith('og:') && key !== 'og:title' && key !== 'og:description' && \r\n key !== 'og:type' && key !== 'og:url' && key !== 'og:image' && \r\n key !== 'og:imageWidth' && key !== 'og:imageHeight' && \r\n key !== 'og:imageAlt' && key !== 'og:siteName' && key !== 'og:locale') {\r\n const value = og[key as keyof OpenGraphMeta];\r\n if (value !== undefined && value !== null && value !== '') {\r\n setMetaProperty(key, value as string | number);\r\n }\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Set Twitter Card meta tags\r\n */\r\nexport function setTwitterCardTags(twitter: TwitterCardMeta): void {\r\n if (!twitter) return;\r\n\r\n if (twitter.card) setMetaTag('twitter:card', twitter.card);\r\n if (twitter.site) setMetaTag('twitter:site', twitter.site);\r\n if (twitter.creator) setMetaTag('twitter:creator', twitter.creator);\r\n if (twitter.title) setMetaTag('twitter:title', twitter.title);\r\n if (twitter.description) setMetaTag('twitter:description', twitter.description);\r\n if (twitter.image) setMetaTag('twitter:image', twitter.image);\r\n if (twitter.imageAlt) setMetaTag('twitter:image:alt', twitter.imageAlt);\r\n\r\n // Handle additional custom twitter:* properties\r\n Object.keys(twitter).forEach((key) => {\r\n if (key.startsWith('twitter:') && key !== 'twitter:card' && key !== 'twitter:site' && \r\n key !== 'twitter:creator' && key !== 'twitter:title' && \r\n key !== 'twitter:description' && key !== 'twitter:image' && \r\n key !== 'twitter:imageAlt') {\r\n const value = twitter[key as keyof TwitterCardMeta];\r\n if (value !== undefined && value !== null && value !== '') {\r\n setMetaTag(key, String(value));\r\n }\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Set custom meta tags\r\n */\r\nexport function setCustomMetaTags(customMeta: CustomMeta[]): void {\r\n if (!customMeta || !Array.isArray(customMeta)) return;\r\n\r\n customMeta.forEach((meta) => {\r\n if (!meta.content) return;\r\n\r\n let element: HTMLMetaElement | null = null;\r\n\r\n if (meta.name) {\r\n element = getOrCreateMetaTag('name', meta.name);\r\n } else if (meta.property) {\r\n element = getOrCreateMetaTag('property', meta.property);\r\n } else if (meta.httpEquiv) {\r\n const selector = `meta[http-equiv=\"${meta.httpEquiv}\"]`;\r\n element = document.querySelector<HTMLMetaElement>(selector);\r\n if (!element) {\r\n element = document.createElement('meta');\r\n element.setAttribute('http-equiv', meta.httpEquiv);\r\n document.head.appendChild(element);\r\n }\r\n } else if (meta.charset) {\r\n let charsetElement = document.querySelector<HTMLMetaElement>('meta[charset]');\r\n if (!charsetElement) {\r\n charsetElement = document.createElement('meta');\r\n charsetElement.setAttribute('charset', meta.charset);\r\n document.head.insertBefore(charsetElement, document.head.firstChild);\r\n }\r\n return;\r\n }\r\n\r\n if (element) {\r\n element.setAttribute('content', meta.content);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Inject JSON-LD structured data\r\n */\r\nexport function injectJsonLd(data: JsonLd, id?: string): () => void {\r\n const script = document.createElement('script');\r\n script.type = 'application/ld+json';\r\n if (id) {\r\n script.id = id;\r\n // Remove existing script with same id\r\n const existing = document.getElementById(id);\r\n if (existing) {\r\n existing.remove();\r\n }\r\n }\r\n script.textContent = JSON.stringify(data);\r\n document.head.appendChild(script);\r\n\r\n // Return cleanup function\r\n return () => {\r\n script.remove();\r\n };\r\n}\r\n\r\n/**\r\n * Remove JSON-LD script by id\r\n */\r\nexport function removeJsonLd(id: string): void {\r\n const script = document.getElementById(id);\r\n if (script && script.getAttribute('type') === 'application/ld+json') {\r\n script.remove();\r\n }\r\n}\r\n\r\n/**\r\n * Format keywords as string\r\n */\r\nexport function formatKeywords(keywords: string | string[] | undefined): string {\r\n if (!keywords) return '';\r\n if (Array.isArray(keywords)) {\r\n return keywords.join(', ');\r\n }\r\n return keywords;\r\n}\r\n\r\n/**\r\n * Remove script by id\r\n */\r\nexport function removeScript(id: string): void {\r\n const script = document.getElementById(id);\r\n if (script && script.tagName === 'SCRIPT') {\r\n script.remove();\r\n }\r\n}\r\n\r\n/**\r\n * Inject Google Analytics script\r\n */\r\nexport function injectGoogleAnalytics(id: string): () => void {\r\n const GA_SCRIPT_ID = 'react-client-seo-ga';\r\n const GA_CONFIG_ID = 'react-client-seo-ga-config';\r\n\r\n // Remove existing scripts if present\r\n removeScript(GA_SCRIPT_ID);\r\n removeScript(GA_CONFIG_ID);\r\n\r\n // Inject gtag.js script\r\n const script = document.createElement('script');\r\n script.id = GA_SCRIPT_ID;\r\n script.async = true;\r\n script.src = `https://www.googletagmanager.com/gtag/js?id=${id}`;\r\n document.head.appendChild(script);\r\n\r\n // Inject gtag config script\r\n const configScript = document.createElement('script');\r\n configScript.id = GA_CONFIG_ID;\r\n configScript.textContent = `\r\n window.dataLayer = window.dataLayer || [];\r\n function gtag(){dataLayer.push(arguments);}\r\n gtag('js', new Date());\r\n gtag('config', '${id}');\r\n `;\r\n document.head.appendChild(configScript);\r\n\r\n // Return cleanup function\r\n return () => {\r\n removeScript(GA_SCRIPT_ID);\r\n removeScript(GA_CONFIG_ID);\r\n };\r\n}\r\n\r\n/**\r\n * Inject Google Tag Manager script\r\n */\r\nexport function injectGoogleTagManager(id: string): () => void {\r\n const GTM_SCRIPT_ID = 'react-client-seo-gtm';\r\n const GTM_NOSCRIPT_ID = 'react-client-seo-gtm-noscript';\r\n\r\n // Remove existing scripts if present\r\n removeScript(GTM_SCRIPT_ID);\r\n const existingNoscript = document.getElementById(GTM_NOSCRIPT_ID);\r\n if (existingNoscript) {\r\n existingNoscript.remove();\r\n }\r\n\r\n // Inject GTM script\r\n const script = document.createElement('script');\r\n script.id = GTM_SCRIPT_ID;\r\n script.textContent = `\r\n (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':\r\n new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],\r\n j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=\r\n 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);\r\n })(window,document,'script','dataLayer','${id}');\r\n `;\r\n document.head.appendChild(script);\r\n\r\n // Inject GTM noscript (in body, but we'll add it to head with a marker)\r\n // Note: GTM noscript should ideally be in body, but for client-side rendering\r\n // we'll inject it and let the user know they may need to add it to body manually\r\n const noscript = document.createElement('noscript');\r\n noscript.id = GTM_NOSCRIPT_ID;\r\n noscript.innerHTML = `<iframe src=\"https://www.googletagmanager.com/ns.html?id=${id}\" height=\"0\" width=\"0\" style=\"display:none;visibility:hidden\"></iframe>`;\r\n document.head.appendChild(noscript);\r\n\r\n // Return cleanup function\r\n return () => {\r\n removeScript(GTM_SCRIPT_ID);\r\n const noscriptEl = document.getElementById(GTM_NOSCRIPT_ID);\r\n if (noscriptEl) {\r\n noscriptEl.remove();\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Inject custom script\r\n */\r\nexport function injectCustomScript(scriptConfig: CustomScript): () => void {\r\n if (!scriptConfig.src && !scriptConfig.content) {\r\n console.warn('CustomScript must have either src or content');\r\n return () => {};\r\n }\r\n\r\n const scriptId = scriptConfig.id || `react-client-seo-custom-${Date.now()}`;\r\n\r\n // Remove existing script if present\r\n if (scriptConfig.id) {\r\n removeScript(scriptConfig.id);\r\n }\r\n\r\n const script = document.createElement('script');\r\n script.id = scriptId;\r\n\r\n if (scriptConfig.src) {\r\n script.src = scriptConfig.src;\r\n }\r\n\r\n if (scriptConfig.content) {\r\n script.textContent = scriptConfig.content;\r\n }\r\n\r\n // Set script attributes\r\n if (scriptConfig.type) {\r\n script.type = scriptConfig.type;\r\n } else {\r\n script.type = 'text/javascript';\r\n }\r\n\r\n if (scriptConfig.strategy === 'async' || scriptConfig.async) {\r\n script.async = true;\r\n }\r\n\r\n if (scriptConfig.strategy === 'defer' || scriptConfig.defer) {\r\n script.defer = true;\r\n }\r\n\r\n document.head.appendChild(script);\r\n\r\n // Return cleanup function\r\n return () => {\r\n removeScript(scriptId);\r\n };\r\n}\r\n","import { useEffect } from 'react';\r\nimport type { SeoProps } from './types';\r\nimport {\r\n setTitle,\r\n setMetaTag,\r\n setCanonical,\r\n setOpenGraphTags,\r\n setTwitterCardTags,\r\n setCustomMetaTags,\r\n injectJsonLd,\r\n formatKeywords,\r\n injectGoogleAnalytics,\r\n injectGoogleTagManager,\r\n injectCustomScript,\r\n} from './utils';\r\n\r\nconst JSON_LD_ID = 'react-client-seo-jsonld';\r\n\r\n/**\r\n * SEO Component\r\n * \r\n * Renders and updates SEO meta tags in the document head.\r\n * Returns null (no UI rendering).\r\n * \r\n * @example\r\n * ```tsx\r\n * <Seo\r\n * title=\"My Page Title\"\r\n * description=\"Page description\"\r\n * keywords={['react', 'seo']}\r\n * canonical=\"https://example.com/page\"\r\n * ogImage=\"https://example.com/image.jpg\"\r\n * jsonLd={{ \"@context\": \"https://schema.org\", \"@type\": \"WebPage\" }}\r\n * />\r\n * ```\r\n */\r\nexport function Seo({\r\n title,\r\n description,\r\n keywords,\r\n author,\r\n robots,\r\n language,\r\n viewport,\r\n generator,\r\n revisitAfter,\r\n rating,\r\n distribution,\r\n copyright,\r\n themeColor,\r\n referrer,\r\n formatDetection,\r\n mobileWebAppCapable,\r\n appleMobileWebAppCapable,\r\n geoRegion,\r\n geoPlacename,\r\n geoPosition,\r\n icbm,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n googleAnalyticsId,\r\n googleTagManagerId,\r\n customScripts,\r\n}: SeoProps) {\r\n useEffect(() => {\r\n // Set title\r\n if (title) {\r\n setTitle(title);\r\n }\r\n\r\n // Set description\r\n if (description) {\r\n setMetaTag('description', description);\r\n }\r\n\r\n // Set keywords\r\n const keywordsStr = formatKeywords(keywords);\r\n if (keywordsStr) {\r\n setMetaTag('keywords', keywordsStr);\r\n }\r\n\r\n // Set author\r\n if (author) {\r\n setMetaTag('author', author);\r\n }\r\n\r\n // Set robots\r\n if (robots) {\r\n setMetaTag('robots', robots);\r\n }\r\n\r\n // Set language\r\n if (language) {\r\n setMetaTag('language', language);\r\n setMetaTag('content-language', language);\r\n }\r\n\r\n // Set viewport\r\n if (viewport) {\r\n setMetaTag('viewport', viewport);\r\n }\r\n\r\n // Set generator\r\n if (generator) {\r\n setMetaTag('generator', generator);\r\n }\r\n\r\n // Set revisit-after\r\n if (revisitAfter) {\r\n setMetaTag('revisit-after', revisitAfter);\r\n }\r\n\r\n // Set rating\r\n if (rating) {\r\n setMetaTag('rating', rating);\r\n }\r\n\r\n // Set distribution\r\n if (distribution) {\r\n setMetaTag('distribution', distribution);\r\n }\r\n\r\n // Set copyright\r\n if (copyright) {\r\n setMetaTag('copyright', copyright);\r\n }\r\n\r\n // Set theme-color\r\n if (themeColor) {\r\n setMetaTag('theme-color', themeColor);\r\n }\r\n\r\n // Set referrer\r\n if (referrer) {\r\n setMetaTag('referrer', referrer);\r\n }\r\n\r\n // Set format-detection\r\n if (formatDetection) {\r\n setMetaTag('format-detection', formatDetection);\r\n }\r\n\r\n // Set mobile-web-app-capable\r\n if (mobileWebAppCapable) {\r\n setMetaTag('mobile-web-app-capable', mobileWebAppCapable);\r\n }\r\n\r\n // Set apple-mobile-web-app-capable\r\n if (appleMobileWebAppCapable) {\r\n setMetaTag('apple-mobile-web-app-capable', appleMobileWebAppCapable);\r\n }\r\n\r\n // Set geo tags\r\n if (geoRegion) {\r\n setMetaTag('geo.region', geoRegion);\r\n }\r\n if (geoPlacename) {\r\n setMetaTag('geo.placename', geoPlacename);\r\n }\r\n if (geoPosition) {\r\n setMetaTag('geo.position', geoPosition);\r\n }\r\n if (icbm) {\r\n setMetaTag('ICBM', icbm);\r\n }\r\n\r\n // Set canonical URL\r\n if (canonical) {\r\n setCanonical(canonical);\r\n }\r\n\r\n // Build Open Graph object\r\n const ogData: any = {\r\n ...openGraph,\r\n };\r\n\r\n if (ogTitle || title) {\r\n ogData.title = ogTitle || title;\r\n }\r\n if (ogDescription || description) {\r\n ogData.description = ogDescription || description;\r\n }\r\n if (ogType) {\r\n ogData.type = ogType;\r\n }\r\n if (ogUrl || canonical) {\r\n ogData.url = ogUrl || canonical;\r\n }\r\n if (ogImage) {\r\n ogData.image = ogImage;\r\n }\r\n if (ogSiteName) {\r\n ogData.siteName = ogSiteName;\r\n }\r\n if (ogLocale) {\r\n ogData.locale = ogLocale;\r\n }\r\n\r\n if (Object.keys(ogData).length > 0) {\r\n setOpenGraphTags(ogData);\r\n }\r\n\r\n // Build Twitter Card object\r\n const twitterData: any = {\r\n ...twitter,\r\n };\r\n\r\n if (twitterCard) {\r\n twitterData.card = twitterCard;\r\n }\r\n if (twitterSite) {\r\n twitterData.site = twitterSite;\r\n }\r\n if (twitterCreator) {\r\n twitterData.creator = twitterCreator;\r\n }\r\n if (twitterTitle || title) {\r\n twitterData.title = twitterTitle || title;\r\n }\r\n if (twitterDescription || description) {\r\n twitterData.description = twitterDescription || description;\r\n }\r\n if (twitterImage || ogImage) {\r\n twitterData.image = twitterImage || ogImage;\r\n }\r\n if (twitterImageAlt) {\r\n twitterData.imageAlt = twitterImageAlt;\r\n }\r\n\r\n if (Object.keys(twitterData).length > 0) {\r\n setTwitterCardTags(twitterData);\r\n }\r\n\r\n // Set custom meta tags\r\n if (customMeta) {\r\n setCustomMetaTags(customMeta);\r\n }\r\n\r\n // Inject JSON-LD\r\n let cleanupJsonLd: (() => void) | null = null;\r\n if (jsonLd) {\r\n cleanupJsonLd = injectJsonLd(jsonLd, JSON_LD_ID);\r\n }\r\n\r\n // Inject Google Analytics\r\n let cleanupGA: (() => void) | null = null;\r\n if (googleAnalyticsId) {\r\n cleanupGA = injectGoogleAnalytics(googleAnalyticsId);\r\n }\r\n\r\n // Inject Google Tag Manager\r\n let cleanupGTM: (() => void) | null = null;\r\n if (googleTagManagerId) {\r\n cleanupGTM = injectGoogleTagManager(googleTagManagerId);\r\n }\r\n\r\n // Inject custom scripts\r\n const cleanupCustomScripts: (() => void)[] = [];\r\n if (customScripts && Array.isArray(customScripts)) {\r\n customScripts.forEach((scriptConfig) => {\r\n const cleanup = injectCustomScript(scriptConfig);\r\n cleanupCustomScripts.push(cleanup);\r\n });\r\n }\r\n\r\n // Cleanup function\r\n return () => {\r\n if (cleanupJsonLd) {\r\n cleanupJsonLd();\r\n }\r\n if (cleanupGA) {\r\n cleanupGA();\r\n }\r\n if (cleanupGTM) {\r\n cleanupGTM();\r\n }\r\n cleanupCustomScripts.forEach((cleanup) => cleanup());\r\n };\r\n }, [\r\n title,\r\n description,\r\n keywords,\r\n author,\r\n robots,\r\n language,\r\n viewport,\r\n generator,\r\n revisitAfter,\r\n rating,\r\n distribution,\r\n copyright,\r\n themeColor,\r\n referrer,\r\n formatDetection,\r\n mobileWebAppCapable,\r\n appleMobileWebAppCapable,\r\n geoRegion,\r\n geoPlacename,\r\n geoPosition,\r\n icbm,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n googleAnalyticsId,\r\n googleTagManagerId,\r\n customScripts,\r\n ]);\r\n\r\n return null;\r\n}\r\n\r\n","import { useCallback } from 'react';\r\nimport type { SeoProps, UseSeoReturn } from './types';\r\nimport {\r\n setTitle,\r\n setMetaTag,\r\n setCanonical,\r\n setOpenGraphTags,\r\n setTwitterCardTags,\r\n setCustomMetaTags,\r\n injectJsonLd,\r\n formatKeywords,\r\n removeCanonical,\r\n removeJsonLd,\r\n injectGoogleAnalytics,\r\n injectGoogleTagManager,\r\n injectCustomScript,\r\n} from './utils';\r\n\r\nconst JSON_LD_ID = 'react-client-seo-jsonld';\r\n\r\n/**\r\n * useSeo Hook\r\n * \r\n * Hook-based API for managing SEO meta tags.\r\n * \r\n * @example\r\n * ```tsx\r\n * function MyComponent() {\r\n * const { updateSeo } = useSeo();\r\n * \r\n * useEffect(() => {\r\n * updateSeo({\r\n * title: 'My Page',\r\n * description: 'Page description',\r\n * });\r\n * }, []);\r\n * \r\n * return <div>Content</div>;\r\n * }\r\n * ```\r\n */\r\nexport function useSeo(): UseSeoReturn {\r\n const updateSeo = useCallback((props: SeoProps) => {\r\n const {\r\n title,\r\n description,\r\n keywords,\r\n author,\r\n robots,\r\n language,\r\n viewport,\r\n generator,\r\n revisitAfter,\r\n rating,\r\n distribution,\r\n copyright,\r\n themeColor,\r\n referrer,\r\n formatDetection,\r\n mobileWebAppCapable,\r\n appleMobileWebAppCapable,\r\n geoRegion,\r\n geoPlacename,\r\n geoPosition,\r\n icbm,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n googleAnalyticsId,\r\n googleTagManagerId,\r\n customScripts,\r\n } = props;\r\n\r\n // Set title\r\n if (title) {\r\n setTitle(title);\r\n }\r\n\r\n // Set description\r\n if (description) {\r\n setMetaTag('description', description);\r\n }\r\n\r\n // Set keywords\r\n const keywordsStr = formatKeywords(keywords);\r\n if (keywordsStr) {\r\n setMetaTag('keywords', keywordsStr);\r\n }\r\n\r\n // Set author\r\n if (author) {\r\n setMetaTag('author', author);\r\n }\r\n\r\n // Set robots\r\n if (robots) {\r\n setMetaTag('robots', robots);\r\n }\r\n\r\n // Set language\r\n if (language) {\r\n setMetaTag('language', language);\r\n setMetaTag('content-language', language);\r\n }\r\n\r\n // Set viewport\r\n if (viewport) {\r\n setMetaTag('viewport', viewport);\r\n }\r\n\r\n // Set generator\r\n if (generator) {\r\n setMetaTag('generator', generator);\r\n }\r\n\r\n // Set revisit-after\r\n if (revisitAfter) {\r\n setMetaTag('revisit-after', revisitAfter);\r\n }\r\n\r\n // Set rating\r\n if (rating) {\r\n setMetaTag('rating', rating);\r\n }\r\n\r\n // Set distribution\r\n if (distribution) {\r\n setMetaTag('distribution', distribution);\r\n }\r\n\r\n // Set copyright\r\n if (copyright) {\r\n setMetaTag('copyright', copyright);\r\n }\r\n\r\n // Set theme-color\r\n if (themeColor) {\r\n setMetaTag('theme-color', themeColor);\r\n }\r\n\r\n // Set referrer\r\n if (referrer) {\r\n setMetaTag('referrer', referrer);\r\n }\r\n\r\n // Set format-detection\r\n if (formatDetection) {\r\n setMetaTag('format-detection', formatDetection);\r\n }\r\n\r\n // Set mobile-web-app-capable\r\n if (mobileWebAppCapable) {\r\n setMetaTag('mobile-web-app-capable', mobileWebAppCapable);\r\n }\r\n\r\n // Set apple-mobile-web-app-capable\r\n if (appleMobileWebAppCapable) {\r\n setMetaTag('apple-mobile-web-app-capable', appleMobileWebAppCapable);\r\n }\r\n\r\n // Set geo tags\r\n if (geoRegion) {\r\n setMetaTag('geo.region', geoRegion);\r\n }\r\n if (geoPlacename) {\r\n setMetaTag('geo.placename', geoPlacename);\r\n }\r\n if (geoPosition) {\r\n setMetaTag('geo.position', geoPosition);\r\n }\r\n if (icbm) {\r\n setMetaTag('ICBM', icbm);\r\n }\r\n\r\n // Set canonical URL\r\n if (canonical) {\r\n setCanonical(canonical);\r\n }\r\n\r\n // Build Open Graph object\r\n const ogData: any = {\r\n ...openGraph,\r\n };\r\n\r\n if (ogTitle || title) {\r\n ogData.title = ogTitle || title;\r\n }\r\n if (ogDescription || description) {\r\n ogData.description = ogDescription || description;\r\n }\r\n if (ogType) {\r\n ogData.type = ogType;\r\n }\r\n if (ogUrl || canonical) {\r\n ogData.url = ogUrl || canonical;\r\n }\r\n if (ogImage) {\r\n ogData.image = ogImage;\r\n }\r\n if (ogSiteName) {\r\n ogData.siteName = ogSiteName;\r\n }\r\n if (ogLocale) {\r\n ogData.locale = ogLocale;\r\n }\r\n\r\n if (Object.keys(ogData).length > 0) {\r\n setOpenGraphTags(ogData);\r\n }\r\n\r\n // Build Twitter Card object\r\n const twitterData: any = {\r\n ...twitter,\r\n };\r\n\r\n if (twitterCard) {\r\n twitterData.card = twitterCard;\r\n }\r\n if (twitterSite) {\r\n twitterData.site = twitterSite;\r\n }\r\n if (twitterCreator) {\r\n twitterData.creator = twitterCreator;\r\n }\r\n if (twitterTitle || title) {\r\n twitterData.title = twitterTitle || title;\r\n }\r\n if (twitterDescription || description) {\r\n twitterData.description = twitterDescription || description;\r\n }\r\n if (twitterImage || ogImage) {\r\n twitterData.image = twitterImage || ogImage;\r\n }\r\n if (twitterImageAlt) {\r\n twitterData.imageAlt = twitterImageAlt;\r\n }\r\n\r\n if (Object.keys(twitterData).length > 0) {\r\n setTwitterCardTags(twitterData);\r\n }\r\n\r\n // Set custom meta tags\r\n if (customMeta) {\r\n setCustomMetaTags(customMeta);\r\n }\r\n\r\n // Inject JSON-LD\r\n if (jsonLd) {\r\n injectJsonLd(jsonLd, JSON_LD_ID);\r\n }\r\n\r\n // Inject Google Analytics\r\n if (googleAnalyticsId) {\r\n injectGoogleAnalytics(googleAnalyticsId);\r\n }\r\n\r\n // Inject Google Tag Manager\r\n if (googleTagManagerId) {\r\n injectGoogleTagManager(googleTagManagerId);\r\n }\r\n\r\n // Inject custom scripts\r\n if (customScripts && Array.isArray(customScripts)) {\r\n customScripts.forEach((scriptConfig) => {\r\n injectCustomScript(scriptConfig);\r\n });\r\n }\r\n }, []);\r\n\r\n const clearSeo = useCallback(() => {\r\n // Note: We don't clear title, description, keywords as they might be set by other means\r\n // Only clear what we manage\r\n removeCanonical();\r\n removeJsonLd(JSON_LD_ID);\r\n }, []);\r\n\r\n return {\r\n updateSeo,\r\n clearSeo,\r\n };\r\n}\r\n\r\n"],"names":["getOrCreateMetaTag","attribute","value","selector","element","setMetaTag","name","content","setMetaProperty","property","setTitle","title","setCanonical","url","link","removeCanonical","setOpenGraphTags","og","key","setTwitterCardTags","twitter","setCustomMetaTags","customMeta","meta","charsetElement","injectJsonLd","data","id","script","existing","removeJsonLd","formatKeywords","keywords","removeScript","injectGoogleAnalytics","GA_SCRIPT_ID","GA_CONFIG_ID","configScript","injectGoogleTagManager","GTM_SCRIPT_ID","GTM_NOSCRIPT_ID","existingNoscript","noscript","noscriptEl","injectCustomScript","scriptConfig","scriptId","JSON_LD_ID","Seo","description","author","robots","language","viewport","generator","revisitAfter","rating","distribution","copyright","themeColor","referrer","formatDetection","mobileWebAppCapable","appleMobileWebAppCapable","geoRegion","geoPlacename","geoPosition","icbm","canonical","ogImage","ogType","ogUrl","ogTitle","ogDescription","ogSiteName","ogLocale","twitterCard","twitterSite","twitterCreator","twitterTitle","twitterDescription","twitterImage","twitterImageAlt","jsonLd","openGraph","googleAnalyticsId","googleTagManagerId","customScripts","useEffect","keywordsStr","ogData","twitterData","cleanupJsonLd","cleanupGA","cleanupGTM","cleanupCustomScripts","cleanup","useSeo","updateSeo","useCallback","props","clearSeo"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { Seo } from './Seo';
2
2
  export { useSeo } from './useSeo';
3
- export type { SeoProps, OpenGraphMeta, TwitterCardMeta, CustomMeta, JsonLd, UseSeoReturn, } from './types';
3
+ export type { SeoProps, OpenGraphMeta, TwitterCardMeta, CustomMeta, CustomScript, JsonLd, UseSeoReturn, } from './types';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EACV,QAAQ,EACR,aAAa,EACb,eAAe,EACf,UAAU,EACV,MAAM,EACN,YAAY,GACb,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EACV,QAAQ,EACR,aAAa,EACb,eAAe,EACf,UAAU,EACV,YAAY,EACZ,MAAM,EACN,YAAY,GACb,MAAM,SAAS,CAAC"}