lytx 0.3.0

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.
Files changed (213) hide show
  1. package/.env.example +37 -0
  2. package/README.md +486 -0
  3. package/alchemy.run.ts +155 -0
  4. package/cli/bootstrap-admin.ts +284 -0
  5. package/cli/deploy-staging.ts +692 -0
  6. package/cli/import-events.ts +628 -0
  7. package/cli/import-sites.ts +518 -0
  8. package/cli/index.ts +609 -0
  9. package/cli/init-db.ts +269 -0
  10. package/cli/migrate-to-durable-objects.ts +564 -0
  11. package/cli/migration-worker.ts +300 -0
  12. package/cli/performance-test.ts +588 -0
  13. package/cli/pg/client.ts +4 -0
  14. package/cli/pg/new-site.ts +153 -0
  15. package/cli/rollback-durable-objects.ts +622 -0
  16. package/cli/seed-data.ts +459 -0
  17. package/cli/setup.js +18 -0
  18. package/cli/setup.ts +463 -0
  19. package/cli/validate-migration.ts +200 -0
  20. package/cli/wrangler-migration.jsonc +28 -0
  21. package/db/adapter.ts +166 -0
  22. package/db/analytics_engine/client.ts +0 -0
  23. package/db/analytics_engine/sites.ts +0 -0
  24. package/db/client.ts +16 -0
  25. package/db/d1/client.ts +8 -0
  26. package/db/d1/drizzle.config.ts +35 -0
  27. package/db/d1/migrations/0000_true_maelstrom.sql +165 -0
  28. package/db/d1/migrations/0001_wonderful_bloodaxe.sql +12 -0
  29. package/db/d1/migrations/0002_late_frightful_four.sql +1 -0
  30. package/db/d1/migrations/0003_cuddly_obadiah_stane.sql +16 -0
  31. package/db/d1/migrations/0004_mute_stardust.sql +1 -0
  32. package/db/d1/migrations/0005_awesome_silvermane.sql +3 -0
  33. package/db/d1/migrations/0006_volatile_shriek.sql +2 -0
  34. package/db/d1/migrations/0007_superb_lila_cheney.sql +1 -0
  35. package/db/d1/migrations/0008_bitter_longshot.sql +17 -0
  36. package/db/d1/migrations/0009_wonderful_madame_masque.sql +28 -0
  37. package/db/d1/migrations/meta/0000_snapshot.json +1112 -0
  38. package/db/d1/migrations/meta/0001_snapshot.json +1187 -0
  39. package/db/d1/migrations/meta/0002_snapshot.json +1194 -0
  40. package/db/d1/migrations/meta/0003_snapshot.json +1296 -0
  41. package/db/d1/migrations/meta/0004_snapshot.json +1303 -0
  42. package/db/d1/migrations/meta/0005_snapshot.json +1325 -0
  43. package/db/d1/migrations/meta/0006_snapshot.json +1339 -0
  44. package/db/d1/migrations/meta/0007_snapshot.json +1347 -0
  45. package/db/d1/migrations/meta/0008_snapshot.json +1464 -0
  46. package/db/d1/migrations/meta/0009_snapshot.json +1648 -0
  47. package/db/d1/migrations/meta/_journal.json +76 -0
  48. package/db/d1/schema.ts +407 -0
  49. package/db/d1/sites.ts +374 -0
  50. package/db/d1/teamAiUsage.ts +101 -0
  51. package/db/d1/teams.ts +127 -0
  52. package/db/durable/drizzle.config.ts +8 -0
  53. package/db/durable/durableObjectClient.ts +480 -0
  54. package/db/durable/events.ts +100 -0
  55. package/db/durable/migrations/0000_fair_bucky.sql +38 -0
  56. package/db/durable/migrations/meta/0000_snapshot.json +278 -0
  57. package/db/durable/migrations/meta/_journal.json +13 -0
  58. package/db/durable/migrations/migrations.js +10 -0
  59. package/db/durable/schema.ts +5 -0
  60. package/db/durable/siteDurableObject.ts +1352 -0
  61. package/db/durable/types.ts +53 -0
  62. package/db/postgres/client.ts +13 -0
  63. package/db/postgres/drizzle.config.ts +12 -0
  64. package/db/postgres/migrations/0000_brainy_sprite.sql +116 -0
  65. package/db/postgres/migrations/meta/0000_snapshot.json +681 -0
  66. package/db/postgres/migrations/meta/_journal.json +13 -0
  67. package/db/postgres/schema.ts +145 -0
  68. package/db/postgres/sites.ts +118 -0
  69. package/db/tranformReports.ts +595 -0
  70. package/db/types.ts +55 -0
  71. package/endpoints/api_worker.tsx +1854 -0
  72. package/endpoints/site_do_worker.ts +11 -0
  73. package/index.d.ts +63 -0
  74. package/index.ts +83 -0
  75. package/lib/auth.ts +279 -0
  76. package/lib/geojson/world_countries.json +45307 -0
  77. package/lib/random_name.ts +41 -0
  78. package/lib/sendMail.ts +252 -0
  79. package/package.json +142 -0
  80. package/public/favicon.ico +0 -0
  81. package/public/images/android-chrome-192x192.png +0 -0
  82. package/public/images/android-chrome-512x512.png +0 -0
  83. package/public/images/apple-touch-icon.png +0 -0
  84. package/public/images/favicon-16x16.png +0 -0
  85. package/public/images/favicon-32x32.png +0 -0
  86. package/public/images/lytx_dark_dashboard.png +0 -0
  87. package/public/images/lytx_light_dashboard.png +0 -0
  88. package/public/images/safari-pinned-tab.svg +4 -0
  89. package/public/logo.png +0 -0
  90. package/public/site.webmanifest +26 -0
  91. package/public/sw.js +107 -0
  92. package/src/Document.tsx +86 -0
  93. package/src/api/ai_api.ts +1156 -0
  94. package/src/api/authMiddleware.ts +45 -0
  95. package/src/api/auth_api.ts +465 -0
  96. package/src/api/event_labels_api.ts +193 -0
  97. package/src/api/events_api.ts +210 -0
  98. package/src/api/queueWorker.ts +303 -0
  99. package/src/api/reports_api.ts +278 -0
  100. package/src/api/seed_api.ts +288 -0
  101. package/src/api/sites_api.ts +904 -0
  102. package/src/api/tag_api.ts +458 -0
  103. package/src/api/tag_api_v2.ts +289 -0
  104. package/src/api/team_api.ts +456 -0
  105. package/src/app/Dashboard.tsx +1339 -0
  106. package/src/app/Events.tsx +974 -0
  107. package/src/app/Explore.tsx +312 -0
  108. package/src/app/Layout.tsx +58 -0
  109. package/src/app/Settings.tsx +1302 -0
  110. package/src/app/components/DashboardCard.tsx +118 -0
  111. package/src/app/components/EditableCell.tsx +123 -0
  112. package/src/app/components/EventForm.tsx +93 -0
  113. package/src/app/components/MarketingFooter.tsx +49 -0
  114. package/src/app/components/MarketingNav.tsx +150 -0
  115. package/src/app/components/Nav.tsx +755 -0
  116. package/src/app/components/NewSiteSetup.tsx +298 -0
  117. package/src/app/components/SQLEditor.tsx +740 -0
  118. package/src/app/components/SiteSelector.tsx +126 -0
  119. package/src/app/components/SiteTag.tsx +42 -0
  120. package/src/app/components/SiteTagInstallCard.tsx +241 -0
  121. package/src/app/components/WorldMapCard.tsx +337 -0
  122. package/src/app/components/charts/ChartComponents.tsx +1481 -0
  123. package/src/app/components/charts/EventFunnel.tsx +45 -0
  124. package/src/app/components/charts/EventSummary.tsx +194 -0
  125. package/src/app/components/charts/SankeyFlows.tsx +72 -0
  126. package/src/app/components/marketing/CheckIcon.tsx +16 -0
  127. package/src/app/components/marketing/MarketingLayout.tsx +23 -0
  128. package/src/app/components/marketing/SectionHeading.tsx +35 -0
  129. package/src/app/components/reports/AskAiWorkspace.tsx +371 -0
  130. package/src/app/components/reports/CreateReportStarter.tsx +74 -0
  131. package/src/app/components/reports/DashboardRouteFiltersContext.tsx +14 -0
  132. package/src/app/components/reports/DashboardToolbar.tsx +154 -0
  133. package/src/app/components/reports/DashboardWorkspaceLayout.tsx +63 -0
  134. package/src/app/components/reports/DashboardWorkspaceShell.tsx +118 -0
  135. package/src/app/components/reports/ReportBuilderWorkspace.tsx +76 -0
  136. package/src/app/components/reports/custom/CustomReportBuilderPage.tsx +1667 -0
  137. package/src/app/components/reports/custom/ReportWidgetChart.tsx +297 -0
  138. package/src/app/components/reports/custom/buildWidgetSql.ts +151 -0
  139. package/src/app/components/reports/custom/chartPalettes.ts +18 -0
  140. package/src/app/components/reports/custom/types.ts +50 -0
  141. package/src/app/components/reports/reportBuilderMenuItems.ts +17 -0
  142. package/src/app/components/reports/useDashboardToolbarControls.tsx +235 -0
  143. package/src/app/components/ui/AlertBanner.tsx +101 -0
  144. package/src/app/components/ui/Button.tsx +55 -0
  145. package/src/app/components/ui/Card.tsx +80 -0
  146. package/src/app/components/ui/Input.tsx +72 -0
  147. package/src/app/components/ui/Link.tsx +23 -0
  148. package/src/app/components/ui/ReportBuilderMenu.tsx +246 -0
  149. package/src/app/components/ui/ThemeToggle.tsx +54 -0
  150. package/src/app/constants.ts +6 -0
  151. package/src/app/headers.ts +33 -0
  152. package/src/app/providers/AuthProvider.tsx +189 -0
  153. package/src/app/providers/ClientProviders.tsx +18 -0
  154. package/src/app/providers/QueryProvider.tsx +23 -0
  155. package/src/app/providers/ThemeProvider.tsx +88 -0
  156. package/src/app/utils/chartThemes.ts +146 -0
  157. package/src/app/utils/keybinds.ts +96 -0
  158. package/src/app/utils/media.tsx +24 -0
  159. package/src/client.tsx +114 -0
  160. package/src/config/createLytxAppConfig.ts +252 -0
  161. package/src/config/resourceNames.ts +88 -0
  162. package/src/db/index.ts +67 -0
  163. package/src/index.css +285 -0
  164. package/src/lib/featureFlags.ts +69 -0
  165. package/src/pages/GetStarted.tsx +290 -0
  166. package/src/pages/Home.tsx +268 -0
  167. package/src/pages/Login.tsx +283 -0
  168. package/src/pages/PrivacyPolicy.tsx +120 -0
  169. package/src/pages/Signup.tsx +267 -0
  170. package/src/pages/TermsOfService.tsx +126 -0
  171. package/src/pages/VerifyEmail.tsx +56 -0
  172. package/src/session/durableObject.ts +7 -0
  173. package/src/session/siteSchema.ts +86 -0
  174. package/src/session/types.ts +36 -0
  175. package/src/templates/README.md +80 -0
  176. package/src/templates/cleanFunctions.js +44 -0
  177. package/src/templates/embedFunctions.js +52 -0
  178. package/src/templates/lytx-shared.ts +662 -0
  179. package/src/templates/lytxpixel-core.ts +144 -0
  180. package/src/templates/lytxpixel.ts +267 -0
  181. package/src/templates/lytxpixelBrowser.js +634 -0
  182. package/src/templates/lytxpixelBrowser.mjs +634 -0
  183. package/src/templates/parseData.js +12 -0
  184. package/src/templates/script.ts +31 -0
  185. package/src/templates/template.tsx +50 -0
  186. package/src/templates/test.js +3 -0
  187. package/src/templates/trackWebEvents.ts +177 -0
  188. package/src/templates/vendors/clickcease.ts +8 -0
  189. package/src/templates/vendors/google.ts +174 -0
  190. package/src/templates/vendors/linkedin.ts +23 -0
  191. package/src/templates/vendors/meta.ts +56 -0
  192. package/src/templates/vendors/quantcast.ts +22 -0
  193. package/src/templates/vendors/simplfi.ts +7 -0
  194. package/src/types/app-context.ts +16 -0
  195. package/src/utilities/dashboardParams.ts +188 -0
  196. package/src/utilities/dashboardQueries.ts +537 -0
  197. package/src/utilities/dashboardTransforms.ts +167 -0
  198. package/src/utilities/dataValidation.ts +414 -0
  199. package/src/utilities/detector.ts +73 -0
  200. package/src/utilities/encrypt.ts +103 -0
  201. package/src/utilities/index.ts +13 -0
  202. package/src/utilities/parser.ts +117 -0
  203. package/src/utilities/performanceMonitoring.ts +570 -0
  204. package/src/utilities/route_interuptors.ts +24 -0
  205. package/src/worker.tsx +675 -0
  206. package/tsconfig.json +78 -0
  207. package/types/env.d.ts +16 -0
  208. package/types/rw.d.ts +7 -0
  209. package/types/shims.d.ts +53 -0
  210. package/types/vite.d.ts +19 -0
  211. package/vite/vite-plugin-pixel-bundle.ts +126 -0
  212. package/vite.config.ts +53 -0
  213. package/worker-configuration.d.ts +8401 -0
@@ -0,0 +1,126 @@
1
+ import { MarketingLayout } from "@/app/components/marketing/MarketingLayout";
2
+ import { SectionHeading } from "@/app/components/marketing/SectionHeading";
3
+
4
+ export function TermsOfService() {
5
+ return (
6
+ <MarketingLayout>
7
+ <section className="pt-32 pb-20">
8
+ <div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
9
+ <SectionHeading
10
+ as="h1"
11
+ badge="Legal"
12
+ title="Terms of Service"
13
+ subtitle="These terms govern your use of the Lytx product provided by Riche Ventures, Inc."
14
+ />
15
+
16
+ <div className="space-y-8 text-slate-600 dark:text-slate-400">
17
+ <p className="text-sm text-slate-500 dark:text-slate-500">Last updated: January 29, 2026</p>
18
+
19
+ <div className="space-y-3">
20
+ <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Agreement to these terms</h2>
21
+ <p>
22
+ By accessing or using the Services, you agree to these Terms of Service ("Terms"). If
23
+ you are using the Services on behalf of an organization, you represent that you have
24
+ authority to bind that organization to these Terms.
25
+ </p>
26
+ </div>
27
+
28
+ <div className="space-y-3">
29
+ <h2 className="text-lg font-semibold text-slate-900 dark:text-white">About Lytx</h2>
30
+ <p>
31
+ Lytx is a product of Riche Ventures, Inc. ("Riche Ventures", "we", "us"). The
32
+ Services provide privacy-first analytics tools, including hosted and self-hosted
33
+ options.
34
+ </p>
35
+ </div>
36
+
37
+ <div className="space-y-3">
38
+ <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Accounts and security</h2>
39
+ <ul className="space-y-2 list-disc pl-5">
40
+ <li>You are responsible for maintaining the confidentiality of your account.</li>
41
+ <li>You agree to provide accurate information and keep it up to date.</li>
42
+ <li>You must notify us promptly of any unauthorized use of your account.</li>
43
+ </ul>
44
+ </div>
45
+
46
+ <div className="space-y-3">
47
+ <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Acceptable use</h2>
48
+ <ul className="space-y-2 list-disc pl-5">
49
+ <li>Do not use the Services for unlawful, harmful, or abusive activities.</li>
50
+ <li>Do not attempt to interfere with or disrupt the Services or networks.</li>
51
+ <li>Do not access or use the Services to build a competing product.</li>
52
+ </ul>
53
+ </div>
54
+
55
+ <div className="space-y-3">
56
+ <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Your data</h2>
57
+ <p>
58
+ You retain ownership of the data you send to the Services. You grant us a limited
59
+ license to process that data to provide and improve the Services. For analytics data
60
+ collected from your sites, you are responsible for providing any required notices to
61
+ your users.
62
+ </p>
63
+ </div>
64
+
65
+ <div className="space-y-3">
66
+ <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Open source and self-hosting</h2>
67
+ <p>
68
+ The Lytx codebase is available as open source. If you choose to self-host, you are
69
+ responsible for your hosting environment, security, and compliance obligations.
70
+ </p>
71
+ </div>
72
+
73
+ <div className="space-y-3">
74
+ <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Termination</h2>
75
+ <p>
76
+ You may stop using the Services at any time. We may suspend or terminate access if you
77
+ violate these Terms or if your use poses a security risk.
78
+ </p>
79
+ </div>
80
+
81
+ <div className="space-y-3">
82
+ <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Disclaimers</h2>
83
+ <p>
84
+ The Services are provided "as is" without warranties of any kind, express or implied.
85
+ We do not warrant that the Services will be uninterrupted or error-free.
86
+ </p>
87
+ </div>
88
+
89
+ <div className="space-y-3">
90
+ <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Limitation of liability</h2>
91
+ <p>
92
+ To the maximum extent permitted by law, Riche Ventures will not be liable for any
93
+ indirect, incidental, special, or consequential damages arising out of or related to
94
+ your use of the Services.
95
+ </p>
96
+ </div>
97
+
98
+ <div className="space-y-3">
99
+ <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Contact</h2>
100
+ <p>
101
+ Riche Ventures, Inc.<br />
102
+ 390 NE 191st St STE 27725<br />
103
+ Miami, FL 33179<br />
104
+ Email:{" "}
105
+ <a
106
+ href="mailto:legal@yourdomain.com"
107
+ className="text-slate-600 hover:text-amber-600 dark:text-slate-400 dark:hover:text-amber-400 underline underline-offset-4"
108
+ >
109
+ legal@yourdomain.com
110
+ </a>
111
+ </p>
112
+ </div>
113
+
114
+ <div className="space-y-3">
115
+ <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Changes to these terms</h2>
116
+ <p>
117
+ We may update these Terms from time to time. If we make material changes, we will
118
+ update the date above and post the revised Terms.
119
+ </p>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ </section>
124
+ </MarketingLayout>
125
+ );
126
+ }
@@ -0,0 +1,56 @@
1
+ type VerifyEmailStatus =
2
+ | { type: "success"; message: string; callbackURL?: string }
3
+ | { type: "error"; message: string; callbackURL?: string };
4
+
5
+ export function VerifyEmail({ status }: { status: VerifyEmailStatus }) {
6
+ const title = status.type === "success" ? "Email verified" : "Unable to verify email";
7
+ const messageColor = status.type === "success" ? "text-green-600" : "text-red-600";
8
+
9
+ return (
10
+ <div className="flex flex-col justify-center items-center py-12 font-montserrat">
11
+ <div className="flex flex-col min-h-[200px] w-full justify-center items-center px-4">
12
+ <div className="h-auto">
13
+ <span className="text-3xl font-semibold">Lytx</span>
14
+ </div>
15
+
16
+ <div className="h-auto my-4 text-lg font-medium">{title}</div>
17
+
18
+ <div className={`w-full max-w-[420px] text-sm ${messageColor}`}>{status.message}</div>
19
+
20
+ {status.callbackURL ? (
21
+ <div className="mt-4 w-full max-w-[420px] text-sm text-gray-600">
22
+ <div className="mb-2">Redirecting you shortly…</div>
23
+ <a className="underline" href={status.callbackURL}>
24
+ Continue
25
+ </a>
26
+ </div>
27
+ ) : (
28
+ <div className="mt-4 w-full max-w-[420px] text-sm text-gray-600">
29
+ <a className="underline" href="/login">
30
+ Go to sign in
31
+ </a>
32
+ </div>
33
+ )}
34
+
35
+ {status.type === "error" ? (
36
+ <div className="mt-6 w-full max-w-[420px] text-sm text-gray-600">
37
+ <div>If you still need a link, you can resend one from the sign-in page.</div>
38
+ <a className="underline" href="/login">
39
+ Resend verification email
40
+ </a>
41
+ </div>
42
+ ) : null}
43
+
44
+ {status.type === "success" && status.callbackURL ? (
45
+ <script
46
+ dangerouslySetInnerHTML={{
47
+ __html: `setTimeout(() => { window.location.href = ${JSON.stringify(
48
+ status.callbackURL,
49
+ )}; }, 1500);`,
50
+ }}
51
+ />
52
+ ) : null}
53
+ </div>
54
+ </div>
55
+ );
56
+ }
@@ -0,0 +1,7 @@
1
+ import { DurableObject } from "cloudflare:workers";
2
+
3
+
4
+ export class SyncDurableObject extends DurableObject {
5
+
6
+
7
+ }
@@ -0,0 +1,86 @@
1
+ import { sqliteTable, text, integer, index } from "drizzle-orm/sqlite-core";
2
+
3
+ /**
4
+ * Site-specific schema for Durable Objects
5
+ *
6
+ * This schema contains only site-specific data (siteEvents) without auth tables.
7
+ * Each durable object represents a single site, so team_id and site_id are not needed
8
+ * as they are implicit in the durable object context.
9
+ */
10
+
11
+ export const siteEvents = sqliteTable(
12
+ "site_events",
13
+ {
14
+ id: integer("id").primaryKey({ autoIncrement: true }),
15
+ // Note: team_id and site_id removed - implicit in durable object context
16
+ bot_data: text("bot_data", { mode: "json" }),
17
+ browser: text("browser"),
18
+ city: text("city"),
19
+ client_page_url: text("client_page_url"),
20
+ country: text("country"),
21
+ createdAt: integer("created_at", { mode: "timestamp" })
22
+ .$defaultFn(() => new Date())
23
+ .notNull(),
24
+ updatedAt: integer("updated_at", { mode: "timestamp" })
25
+ .$defaultFn(() => new Date())
26
+ .notNull()
27
+ .$onUpdateFn(() => new Date()),
28
+ custom_data: text("custom_data", { mode: "json" }),
29
+ device_type: text("device_type"),
30
+ event: text("event").notNull(),
31
+ operating_system: text("operating_system"),
32
+ page_url: text("page_url"),
33
+ postal: text("postal"),
34
+ query_params: text("query_params", { mode: "json" }),
35
+ referer: text("referer"),
36
+ region: text("region"),
37
+ rid: text("rid"),
38
+ screen_height: integer("screen_height"),
39
+ screen_width: integer("screen_width"),
40
+ tag_id: text("tag_id").notNull(),
41
+ },
42
+ (table) => [
43
+ // Optimized indexes for site-specific queries (no team/site composite indexes needed)
44
+ index("site_events_created_at_idx").on(table.createdAt),
45
+ index("site_events_tag_id_idx").on(table.tag_id),
46
+
47
+ // Analytics filtering indexes
48
+ index("site_events_country_idx").on(table.country),
49
+ index("site_events_device_type_idx").on(table.device_type),
50
+ index("site_events_event_idx").on(table.event),
51
+ index("site_events_referer_idx").on(table.referer),
52
+
53
+ // Time-based analytics (common dashboard queries)
54
+ index("site_events_event_created_idx").on(table.event, table.createdAt),
55
+ index("site_events_country_created_idx").on(table.country, table.createdAt),
56
+ index("site_events_device_created_idx").on(table.device_type, table.createdAt),
57
+ ],
58
+ );
59
+
60
+ // Type definitions for site events
61
+ export type SiteEvent = typeof siteEvents.$inferSelect;
62
+ export type SiteEventInsert = typeof siteEvents.$inferInsert;
63
+
64
+ // Input type for API operations (matches the structure expected from external sources)
65
+ export interface SiteEventInput {
66
+ bot_data?: Record<string, string>;
67
+ browser?: string;
68
+ city?: string;
69
+ client_page_url?: string;
70
+ country?: string;
71
+ custom_data?: Record<string, string>;
72
+ device_type?: string;
73
+ event: string;
74
+ operating_system?: string;
75
+ page_url?: string;
76
+ postal?: string;
77
+ query_params?: Record<string, string>;
78
+ referer?: string;
79
+ region?: string;
80
+ rid?: string;
81
+ screen_height?: number;
82
+ screen_width?: number;
83
+ tag_id: string;
84
+ createdAt?: Date;
85
+ updatedAt?: Date;
86
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Shared types for Site Durable Objects
3
+ */
4
+
5
+ // Input type for API operations (matches the structure expected from external sources)
6
+ export interface SiteEventInput {
7
+ bot_data?: object;
8
+ browser?: string;
9
+ city?: string;
10
+ client_page_url?: string;
11
+ country?: string;
12
+ custom_data?: object;
13
+ device_type?: string;
14
+ event: string;
15
+ operating_system?: string;
16
+ page_url?: string;
17
+ postal?: string;
18
+ query_params?: object;
19
+ referer?: string;
20
+ region?: string;
21
+ rid?: string;
22
+ screen_height?: number;
23
+ screen_width?: number;
24
+ tag_id: string;
25
+ createdAt?: Date;
26
+ updatedAt?: Date;
27
+ }
28
+
29
+ export interface DashboardOptions {
30
+ site_id: number | string;
31
+ team_id: number;
32
+ date?: {
33
+ start?: Date;
34
+ end?: Date;
35
+ };
36
+ }
@@ -0,0 +1,80 @@
1
+ # Lytx Script Templates
2
+
3
+ This directory contains the JavaScript tracking scripts that are bundled and served to client websites.
4
+
5
+ ## Script Variants
6
+
7
+ | Export | File | Description |
8
+ |--------|------|-------------|
9
+ | `script_core` | `lytxpixel-core.ts` | Core tracking only, NO third-party vendors |
10
+ | `script_tag_manager` | `lytxpixel.ts` | Full version WITH third-party vendor integrations |
11
+
12
+ ## IMPORTANT: Tag Manager is OPT-IN
13
+
14
+ **By default, `tag_manager` is DISABLED for all sites.**
15
+
16
+ The `script_core` bundle is served unless a site explicitly enables `tag_manager` in their site configuration.
17
+
18
+ ### What this means:
19
+
20
+ - **`tag_manager = false` (DEFAULT):** Site receives `script_core` - only Lytx event tracking, no third-party scripts
21
+ - **`tag_manager = true` (OPT-IN):** Site receives `script_tag_manager` - includes all vendor integrations
22
+
23
+ ## Cookie & Privacy Compliance Warning
24
+
25
+ **When `tag_manager` is enabled, the following third-party vendor scripts may be loaded:**
26
+
27
+ - Google Analytics / Google Ads
28
+ - Meta (Facebook) Pixel
29
+ - LinkedIn Insight Tag
30
+ - Quantcast
31
+ - SimpleFi
32
+ - ClickCease
33
+
34
+ ### USER RESPONSIBILITY
35
+
36
+ **If you enable `tag_manager` for a site, YOU are responsible for:**
37
+
38
+ 1. **Cookie Consent:** Ensuring proper cookie consent banners/mechanisms are in place
39
+ 2. **Privacy Policy:** Updating the site's privacy policy to disclose third-party tracking
40
+ 3. **GDPR/CCPA Compliance:** Meeting all applicable privacy regulations
41
+ 4. **Vendor Terms:** Complying with each vendor's terms of service
42
+
43
+ **Lytx does NOT manage cookie consent for third-party vendor tags.**
44
+
45
+ The site owner/operator enabling `tag_manager` assumes full responsibility for any cookies or tracking pixels fired by these vendor integrations.
46
+
47
+ ## File Structure
48
+
49
+ ```
50
+ src/templates/
51
+ ├── lytx-shared.ts # Shared types, utilities, core functions
52
+ ├── lytxpixel.ts # Full version (tag_manager enabled)
53
+ ├── lytxpixel-core.ts # Core version (tag_manager disabled)
54
+ ├── trackWebEvents.ts # Event tracking API
55
+ └── vendors/ # Third-party vendor integrations
56
+ ├── google.ts # Google Analytics/Ads
57
+ ├── meta.ts # Meta/Facebook Pixel
58
+ ├── linkedin.ts # LinkedIn Insight Tag
59
+ ├── quantcast.ts # Quantcast
60
+ ├── simplfi.ts # SimpleFi
61
+ └── clickcease.ts # ClickCease
62
+ ```
63
+
64
+ ## How Bundling Works
65
+
66
+ Scripts are bundled at **build time** via the Vite plugin (`vite/vite-plugin-pixel-bundle.ts`):
67
+
68
+ 1. `lytxpixel.ts` and `lytxpixel-core.ts` are bundled using esbuild
69
+ 2. Bundled strings are exposed as virtual module `virtual:lytx-pixel-raw`
70
+ 3. The appropriate bundle is served based on the site's `tag_manager` setting
71
+
72
+ No runtime bundling occurs - both bundles are pre-compiled and embedded in the worker.
73
+
74
+ ## Modifying Scripts
75
+
76
+ - **Shared logic:** Edit `lytx-shared.ts` - changes apply to both versions
77
+ - **Core-only changes:** Edit `lytxpixel-core.ts`
78
+ - **Vendor integration changes:** Edit `lytxpixel.ts` or files in `vendors/`
79
+
80
+ After making changes, run `bun run build` to regenerate the bundles.
@@ -0,0 +1,44 @@
1
+ // Clean JavaScript functions for embedding (no TypeScript artifacts)
2
+
3
+ function parseData(data, config, trackCustomEvents, track_web_events, platformName) {
4
+ const pageUrl = new URL(window.location.href);
5
+ const debug = pageUrl.searchParams.has('lytxDebug');
6
+
7
+ if(window.lytxDataLayer.length < 2) {
8
+ console.log('Lytx script is working 🔥🔥🔥' + (debug ? '🐛🐛🐛 debug enabled' : ''));
9
+ }
10
+
11
+ function createScriptElement(src, async, type) {
12
+ const script = document.createElement("script");
13
+ script.src = src;
14
+ script.async = async;
15
+ let scriptPlacement = document.head.children[0];
16
+ if(!scriptPlacement){
17
+ scriptPlacement = document.getElementsByTagName("script")[0];
18
+ }
19
+ if (type) {
20
+ script.type = type;
21
+ }
22
+ scriptPlacement.parentNode.insertBefore(script, scriptPlacement);
23
+ }
24
+
25
+ function gtag_report_conversion(url) {
26
+ const callback = function() {
27
+ if (typeof url != "undefined") {
28
+ window.location = url;
29
+ }
30
+ };
31
+ gtag('event', 'conversion', {
32
+ 'send_to': 'AW-123456789/AbC-D_efG-h12_34-567',
33
+ 'event_callback': callback
34
+ });
35
+ return false;
36
+ }
37
+
38
+ // Add your other function logic here...
39
+ }
40
+
41
+ function trackEvents(account, platformName, event, macros) {
42
+ // Add trackEvents logic here
43
+ console.log('trackEvents called with:', account, platformName, event);
44
+ }
@@ -0,0 +1,52 @@
1
+ // Standalone functions for embedding in client-side scripts
2
+ // This file will be compiled to clean JavaScript
3
+
4
+ // Copy the parseData function here without TypeScript types
5
+ function parseData(data, config, trackCustomEvents, track_web_events, platformName) {
6
+ const pageUrl = new URL(window.location.href);
7
+ const debug = pageUrl.searchParams.has('lytxDebug');
8
+
9
+ if(window.lytxDataLayer.length < 2) {
10
+ console.log(`Lytx script is working 🔥🔥🔥${debug ? '🐛🐛🐛 debug enabled' : ''}`);
11
+ }
12
+
13
+ function createScriptElement(src, async, type) {
14
+ const script = document.createElement("script");
15
+ script.src = src;
16
+ script.async = async;
17
+ let scriptPlacement = document.head.children[0];
18
+ if(!scriptPlacement){
19
+ scriptPlacement = document.getElementsByTagName("script")[0];
20
+ }
21
+ if (type) {
22
+ script.type = type;
23
+ }
24
+ scriptPlacement.parentNode.insertBefore(script, scriptPlacement);
25
+ }
26
+
27
+ function quantcastScript(label) {
28
+ return {
29
+ async: true,
30
+ src: (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js",
31
+ element: "script",
32
+ callBack: function(id) {
33
+ window._qevents = window._qevents || [];
34
+ if(debug) {
35
+ console.log('Quantcast label is : ', label);
36
+ }
37
+ const qStructure = {
38
+ qacct: label
39
+ };
40
+ window._qevents.push(qStructure);
41
+ }
42
+ };
43
+ }
44
+
45
+ // Add the rest of your parseData logic here...
46
+ // Copy from the TypeScript version but remove all type annotations
47
+ }
48
+
49
+ // Export for compilation
50
+ if (typeof module !== 'undefined' && module.exports) {
51
+ module.exports = { parseData };
52
+ }