@vskstudio/takt-astro 0.2.0 → 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.
- package/Badge.astro +14 -0
- package/Embed.astro +16 -0
- package/README.md +27 -1
- package/Takt.astro +27 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +15 -9
- package/package.json +10 -4
package/Badge.astro
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { badgeUrl, type BadgeVariant, type BadgeGlyph, type WidgetLang } from '@vskstudio/takt-core'
|
|
3
|
+
|
|
4
|
+
type Props = {
|
|
5
|
+
domain: string
|
|
6
|
+
variant?: BadgeVariant
|
|
7
|
+
glyph?: BadgeGlyph
|
|
8
|
+
lang?: WidgetLang
|
|
9
|
+
host?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { domain, variant, glyph, lang, host, ...rest } = Astro.props
|
|
13
|
+
---
|
|
14
|
+
<img src={badgeUrl(domain, { variant, glyph, lang, host })} alt="takt" loading="lazy" decoding="async" {...rest} />
|
package/Embed.astro
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { embedUrl, type EmbedTheme, type WidgetLang } from '@vskstudio/takt-core'
|
|
3
|
+
|
|
4
|
+
type Props = {
|
|
5
|
+
domain: string
|
|
6
|
+
theme?: EmbedTheme
|
|
7
|
+
lang?: WidgetLang
|
|
8
|
+
host?: string
|
|
9
|
+
width?: number | string
|
|
10
|
+
height?: number | string
|
|
11
|
+
title?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { domain, theme, lang, host, width = 404, height = 264, title = 'takt', ...rest } = Astro.props
|
|
15
|
+
---
|
|
16
|
+
<iframe src={embedUrl(domain, { theme, lang, host })} title={title} width={width} height={height} loading="lazy" style="border:0" {...rest}></iframe>
|
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ Both the integration and the component accept the same options:
|
|
|
53
53
|
|
|
54
54
|
## View Transitions
|
|
55
55
|
|
|
56
|
-
Astro's client router
|
|
56
|
+
Astro's client router runs several history operations per navigation (scroll-restoration `replaceState` plus `pushState`), so Takt does **not** rely on core's history patch here — it would over-count. Instead the runtime fires one explicit initial pageview and then one per Astro `astro:after-swap` event (including View Transitions DOM swaps and back/forward), so each navigation is counted exactly once. On a plain MPA (no client router) the script re-runs per page load, which fires the initial pageview each time. The runtime is SSR/prerender safe — it only runs in the browser.
|
|
57
57
|
|
|
58
58
|
## Custom events
|
|
59
59
|
|
|
@@ -65,6 +65,32 @@ import { track } from '@vskstudio/takt-astro'
|
|
|
65
65
|
track('Signup', { revenue: { amount: '9.00', currency: 'USD' } })
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
+
## Widgets
|
|
69
|
+
|
|
70
|
+
Thin wrappers around Takt's server-rendered badge SVG and embed iframe.
|
|
71
|
+
|
|
72
|
+
```astro
|
|
73
|
+
---
|
|
74
|
+
import Badge from '@vskstudio/takt-astro/Badge.astro'
|
|
75
|
+
import Embed from '@vskstudio/takt-astro/Embed.astro'
|
|
76
|
+
---
|
|
77
|
+
<Badge domain="example.com" variant="d" />
|
|
78
|
+
<Embed domain="example.com" theme="dark" />
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`Badge` renders an `<img>` (props: `domain`, `variant`, `glyph`, `lang`, `host`); `Embed` renders an `<iframe>` (props: `domain`, `theme`, `lang`, `host`, `width`, `height`, `title`). Extra attributes pass through to the underlying element.
|
|
82
|
+
|
|
83
|
+
## Public stats
|
|
84
|
+
|
|
85
|
+
`createStats` (re-exported from core) reads public analytics:
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
import { createStats } from '@vskstudio/takt-astro'
|
|
89
|
+
|
|
90
|
+
const stats = createStats({ domain: 'example.com' })
|
|
91
|
+
const summary = await stats.summary({ period: '7d' })
|
|
92
|
+
```
|
|
93
|
+
|
|
68
94
|
## License
|
|
69
95
|
|
|
70
96
|
MIT
|
package/Takt.astro
CHANGED
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
// Import from the built output: the published package ships dist/ + this file,
|
|
3
|
+
// not src/, so a src import would break on install.
|
|
4
|
+
import { resolveOptions, type TaktOptions } from './dist/index.js'
|
|
4
5
|
|
|
5
6
|
type Props = TaktOptions
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
// Options travel as a JSON data island, NOT interpolated into JS, so a domain or
|
|
9
|
+
// endpoint containing `</script>`/quotes can't break out. `<` is escaped so the
|
|
10
|
+
// value can't terminate the island's <script> tag either.
|
|
11
|
+
const config = JSON.stringify(resolveOptions(Astro.props))
|
|
12
|
+
.replace(/</g, '\\u003c')
|
|
13
|
+
.replace(/>/g, '\\u003e')
|
|
14
|
+
.replace(/&/g, '\\u0026')
|
|
8
15
|
---
|
|
9
16
|
<!-- Pick ONE install path — this component OR the integration — not both. -->
|
|
10
|
-
<script
|
|
17
|
+
<script type="application/json" data-takt-config set:html={config}></script>
|
|
18
|
+
<!-- A bundled (non-inline) module so Astro resolves the bare core import; an
|
|
19
|
+
is:inline module would leave it unresolved in the browser. -->
|
|
20
|
+
<script>
|
|
21
|
+
import { init, pageview } from '@vskstudio/takt-core'
|
|
22
|
+
const el = document.querySelector('script[data-takt-config]')
|
|
23
|
+
const w = window as unknown as { __takt?: boolean }
|
|
24
|
+
if (el && !w.__takt) {
|
|
25
|
+
const o = JSON.parse(el.textContent || '{}')
|
|
26
|
+
w.__takt = true
|
|
27
|
+
// auto forced off: Astro's ClientRouter runs several history ops per nav, so
|
|
28
|
+
// core's history patch would over-count. Drive pageviews from after-swap.
|
|
29
|
+
init({ ...o, auto: false })
|
|
30
|
+
pageview()
|
|
31
|
+
if (o.auto !== false) document.addEventListener('astro:after-swap', () => pageview())
|
|
32
|
+
}
|
|
33
|
+
</script>
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AstroIntegration } from 'astro';
|
|
2
2
|
import { InitOptions } from '@vskstudio/takt-core';
|
|
3
|
-
export { InitOptions, TrackOptions, optIn, optOut, pageview, track } from '@vskstudio/takt-core';
|
|
3
|
+
export { BadgeGlyph, BadgeOptions, BadgeVariant, EmbedOptions, EmbedTheme, InitOptions, PublicApiError, StatsBreakdown, StatsBreakdownRow, StatsClient, StatsClientOptions, StatsDimension, StatsMetrics, StatsParams, StatsPeriod, StatsPoint, StatsRealtime, StatsSummary, StatsTimeseries, TrackOptions, WidgetLang, badgeUrl, createStats, embedUrl, optIn, optOut, pageview, track } from '@vskstudio/takt-core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Options for the Takt integration and `<Takt />` component. Mirrors core's
|
package/dist/index.js
CHANGED
|
@@ -13,23 +13,24 @@ function resolveOptions(options = {}) {
|
|
|
13
13
|
|
|
14
14
|
// src/runtime.ts
|
|
15
15
|
function buildRuntime(options) {
|
|
16
|
-
const
|
|
16
|
+
const spa = options.auto !== false;
|
|
17
|
+
const json = JSON.stringify({ ...options, auto: false }).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026");
|
|
17
18
|
return [
|
|
18
|
-
`import { init } from '@vskstudio/takt-core';`,
|
|
19
|
+
`import { init, pageview } from '@vskstudio/takt-core';`,
|
|
19
20
|
// SSR/prerender guard: this module is evaluated under Node when Astro
|
|
20
21
|
// prerenders, where window/init's browser APIs are absent.
|
|
21
22
|
`if (typeof window !== 'undefined' && !window.__takt) {`,
|
|
22
23
|
` const o = ${json};`,
|
|
23
24
|
// Idempotent across both entry paths (integration + <Takt/>): the flag stops
|
|
24
|
-
// a second boot from
|
|
25
|
+
// a second boot from re-registering listeners or re-firing the initial view.
|
|
25
26
|
` window.__takt = true;`,
|
|
26
|
-
// Single source of pageviews. init() enables core's SPA tracking, which
|
|
27
|
-
// patches history.pushState/replaceState. Astro's ClientRouter navigates via
|
|
28
|
-
// pushState and does NOT replace the history object on DOM swap, so the patch
|
|
29
|
-
// persists and fires one pageview per View Transitions navigation. init()
|
|
30
|
-
// also fires the initial pageview. We therefore do NOT listen to
|
|
31
|
-
// astro:page-load — doing so would double-count every in-app navigation.
|
|
32
27
|
` init(o);`,
|
|
28
|
+
// One initial pageview (also covers full-page MPA loads, where the script
|
|
29
|
+
// re-runs per navigation and astro:after-swap never fires).
|
|
30
|
+
` pageview();`,
|
|
31
|
+
// astro:after-swap fires exactly once per ClientRouter navigation (incl.
|
|
32
|
+
// back/forward), giving one pageview per nav with no double-count.
|
|
33
|
+
...spa ? [` document.addEventListener('astro:after-swap', () => pageview());`] : [],
|
|
33
34
|
`}`
|
|
34
35
|
].join("\n");
|
|
35
36
|
}
|
|
@@ -49,9 +50,14 @@ function takt(options = {}) {
|
|
|
49
50
|
|
|
50
51
|
// src/index.ts
|
|
51
52
|
import { track, pageview, optOut, optIn } from "@vskstudio/takt-core";
|
|
53
|
+
import { createStats, PublicApiError, badgeUrl, embedUrl } from "@vskstudio/takt-core";
|
|
52
54
|
export {
|
|
55
|
+
PublicApiError,
|
|
56
|
+
badgeUrl,
|
|
53
57
|
buildRuntime,
|
|
58
|
+
createStats,
|
|
54
59
|
takt as default,
|
|
60
|
+
embedUrl,
|
|
55
61
|
optIn,
|
|
56
62
|
optOut,
|
|
57
63
|
pageview,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vskstudio/takt-astro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Astro integration for Takt privacy-friendly analytics",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "VSK Studio",
|
|
@@ -32,23 +32,28 @@
|
|
|
32
32
|
"default": "./dist/index.js"
|
|
33
33
|
},
|
|
34
34
|
"./Takt.astro": "./Takt.astro",
|
|
35
|
+
"./Badge.astro": "./Badge.astro",
|
|
36
|
+
"./Embed.astro": "./Embed.astro",
|
|
35
37
|
"./package.json": "./package.json"
|
|
36
38
|
},
|
|
37
39
|
"files": [
|
|
38
40
|
"dist",
|
|
39
|
-
"Takt.astro"
|
|
41
|
+
"Takt.astro",
|
|
42
|
+
"Badge.astro",
|
|
43
|
+
"Embed.astro"
|
|
40
44
|
],
|
|
41
45
|
"engines": {
|
|
42
46
|
"node": ">=18"
|
|
43
47
|
},
|
|
44
48
|
"peerDependencies": {
|
|
45
|
-
"@vskstudio/takt-core": ">=0.
|
|
49
|
+
"@vskstudio/takt-core": ">=0.3.0",
|
|
46
50
|
"astro": ">=4"
|
|
47
51
|
},
|
|
48
52
|
"devDependencies": {
|
|
49
53
|
"@changesets/cli": "^2.31.0",
|
|
54
|
+
"@playwright/test": "^1.50.0",
|
|
50
55
|
"@size-limit/preset-small-lib": "^11.1.6",
|
|
51
|
-
"@vskstudio/takt-core": "^0.
|
|
56
|
+
"@vskstudio/takt-core": "^0.3.0",
|
|
52
57
|
"astro": "^5.0.0",
|
|
53
58
|
"eslint": "^9.0.0",
|
|
54
59
|
"size-limit": "^11.1.6",
|
|
@@ -62,6 +67,7 @@
|
|
|
62
67
|
"typecheck": "tsc --noEmit",
|
|
63
68
|
"lint": "eslint .",
|
|
64
69
|
"test": "vitest run",
|
|
70
|
+
"e2e": "playwright test",
|
|
65
71
|
"size": "size-limit",
|
|
66
72
|
"release": "pnpm build && changeset publish"
|
|
67
73
|
}
|