@m13v/seo-components 0.27.0 → 0.28.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m13v/seo-components",
3
- "version": "0.27.0",
3
+ "version": "0.28.1",
4
4
  "scripts": {
5
5
  "build:css": "tailwind -i src/_build.css -o dist/styles.css --minify",
6
6
  "bump:consumers": "bash scripts/bump-consumers.sh",
@@ -58,7 +58,6 @@
58
58
  "lottie-react": ">=2",
59
59
  "next": ">=14",
60
60
  "posthog-js": ">=1.100",
61
- "posthog-node": ">=4",
62
61
  "react": ">=18",
63
62
  "react-dom": ">=18",
64
63
  "remotion": ">=4"
@@ -84,9 +83,6 @@
84
83
  },
85
84
  "posthog-js": {
86
85
  "optional": true
87
- },
88
- "posthog-node": {
89
- "optional": true
90
86
  }
91
87
  },
92
88
  "devDependencies": {
@@ -9,8 +9,18 @@ import React, { useEffect, useRef, useState } from "react";
9
9
  * at mount (falling back to teal #14b8a6). Canvas paint cannot use CSS
10
10
  * vars directly, so we resolve it once via getComputedStyle.
11
11
  *
12
+ * Defaults to `absolute inset-0 pointer-events-none` so it sits as an
13
+ * ambient layer behind its `position: relative` parent (e.g. a hero
14
+ * card). Callers who need a non-default layout can pass `className` to
15
+ * override. Prior to 0.28.1 the default was an empty string, which made
16
+ * the canvas render in-flow and consume 500-700px of hero vertical
17
+ * space, pushing the real hero content off-screen.
18
+ *
12
19
  * @example
13
- * <Particles className="absolute inset-0" quantity={80} />
20
+ * <div className="relative">
21
+ * <Particles quantity={80} />
22
+ * <h1>Hero content on top</h1>
23
+ * </div>
14
24
  */
15
25
 
16
26
  interface MousePosition {
@@ -90,7 +100,7 @@ type Circle = {
90
100
  };
91
101
 
92
102
  export function Particles({
93
- className = "",
103
+ className = "absolute inset-0 pointer-events-none",
94
104
  quantity = 100,
95
105
  staticity = 50,
96
106
  ease = 50,
@@ -17,7 +17,8 @@ export interface BookCallRedirectConfig {
17
17
  * The handler:
18
18
  * 1. Reads `email` and `site` from the query string (unsigned — the blast
19
19
  * radius of forgery is a noisy PostHog event).
20
- * 2. Fires a server-side `book_call_email_link_clicked` PostHog event with
20
+ * 2. Fires a `book_call_email_link_clicked` event to PostHog via the
21
+ * public `/i/v0/e/` HTTP endpoint (no posthog-node dependency), with
21
22
  * `distinct_id = email`. Unique-user dedup is handled by PostHog.
22
23
  * 3. 302s to Cal.com / Calendly with `?email=` pre-filled and
23
24
  * `utm_medium=email_booking_link` so the funnel column separates
@@ -40,33 +41,29 @@ export function createBookCallRedirectHandler(config: BookCallRedirectConfig) {
40
41
  const validEmail = !!email && email.includes("@") && email.length <= 254;
41
42
  const siteMatches = querySite === site;
42
43
 
43
- // If the query is malformed or targeted at a different site, drop to the
44
- // bare booking URL so the user still reaches Cal/Calendly.
45
44
  if (validEmail && siteMatches) {
46
45
  const posthogKey = process.env[posthogKeyEnv];
46
+ const posthogHost = process.env[posthogHostEnv] || "https://us.i.posthog.com";
47
47
  if (posthogKey) {
48
- try {
49
- // Lazy import so sites that never use this handler don't have to
50
- // install posthog-node to satisfy Next.js static analysis.
51
- const { PostHog } = await import("posthog-node");
52
- const ph = new PostHog(posthogKey, {
53
- host: process.env[posthogHostEnv] || "https://us.i.posthog.com",
54
- flushAt: 1,
55
- flushInterval: 0,
56
- });
57
- ph.capture({
58
- distinctId: email,
48
+ // Fire via PostHog's public HTTP capture endpoint. Fire-and-forget
49
+ // with .catch so a PostHog hiccup never delays the 302.
50
+ fetch(`${posthogHost.replace(/\/+$/, "")}/i/v0/e/`, {
51
+ method: "POST",
52
+ headers: { "Content-Type": "application/json" },
53
+ body: JSON.stringify({
54
+ api_key: posthogKey,
59
55
  event: "book_call_email_link_clicked",
56
+ distinct_id: email,
57
+ timestamp: new Date().toISOString(),
60
58
  properties: {
61
59
  site,
62
60
  email,
63
61
  $set: { email },
64
62
  },
65
- });
66
- await ph.shutdown();
67
- } catch (err) {
68
- console.error("[book-call/redirect] posthog capture failed:", err);
69
- }
63
+ }),
64
+ }).catch((err) => {
65
+ console.error("[book-call/redirect] posthog fetch failed:", err);
66
+ });
70
67
  }
71
68
  }
72
69