@nuxt/scripts 0.13.2 → 1.0.0-beta.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 +9 -0
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/{iNmKC7TZ.js → Bdf7Qtwg.js} +1 -1
- package/dist/client/_nuxt/CoyZWCgl.js +162 -0
- package/dist/client/_nuxt/{Bje-0OHL.js → DTDyDxvR.js} +1 -1
- package/dist/client/_nuxt/{rttsH3SL.js → Ds1k3yKJ.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/62574f80-71d4-4f9e-8b96-145c85230d99.json +1 -0
- package/dist/client/_nuxt/error-404.D45Vtjcx.css +1 -0
- package/dist/client/_nuxt/error-500.BOm1rWQf.css +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +26 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +98 -54
- package/dist/registry.mjs +53 -0
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.d.vue.ts +29 -1
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +35 -10
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue.d.ts +29 -1
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.d.vue.ts +20 -8
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarkerClusterer.vue.d.ts +20 -8
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPinElement.vue +7 -1
- package/dist/runtime/components/ScriptCrisp.d.vue.ts +1 -1
- package/dist/runtime/components/ScriptCrisp.vue.d.ts +1 -1
- package/dist/runtime/components/ScriptIntercom.d.vue.ts +1 -1
- package/dist/runtime/components/ScriptIntercom.vue.d.ts +1 -1
- package/dist/runtime/components/ScriptVimeoPlayer.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptVimeoPlayer.vue.d.ts +2 -2
- package/dist/runtime/components/ScriptYouTubePlayer.d.vue.ts +12 -1
- package/dist/runtime/components/ScriptYouTubePlayer.vue +41 -16
- package/dist/runtime/components/ScriptYouTubePlayer.vue.d.ts +12 -1
- package/dist/runtime/composables/useScript.js +10 -0
- package/dist/runtime/npm-script-stub.d.ts +20 -0
- package/dist/runtime/npm-script-stub.js +73 -0
- package/dist/runtime/registry/google-recaptcha.d.ts +27 -0
- package/dist/runtime/registry/google-recaptcha.js +45 -0
- package/dist/runtime/registry/google-sign-in.d.ts +84 -0
- package/dist/runtime/registry/google-sign-in.js +50 -0
- package/dist/runtime/registry/google-tag-manager.d.ts +3 -1
- package/dist/runtime/registry/google-tag-manager.js +15 -5
- package/dist/runtime/registry/matomo-analytics.js +1 -1
- package/dist/runtime/registry/plausible-analytics.js +8 -6
- package/dist/runtime/registry/posthog.d.ts +26 -0
- package/dist/runtime/registry/posthog.js +92 -0
- package/dist/runtime/registry/rybbit-analytics.js +38 -8
- package/dist/runtime/registry/tiktok-pixel.d.ts +43 -0
- package/dist/runtime/registry/tiktok-pixel.js +43 -0
- package/dist/runtime/server/google-static-maps-proxy.d.ts +2 -0
- package/dist/runtime/server/google-static-maps-proxy.js +54 -0
- package/dist/runtime/types.d.ts +13 -1
- package/dist/runtime/utils.d.ts +2 -1
- package/dist/runtime/utils.js +9 -0
- package/package.json +25 -19
- package/dist/client/_nuxt/DMut0W-e.js +0 -162
- package/dist/client/_nuxt/builds/meta/5e0206fe-a683-423c-8d59-2596d0b16fee.json +0 -1
- package/dist/client/_nuxt/error-404.B0ZhSNwd.css +0 -1
- package/dist/client/_nuxt/error-500.D4MdgPaC.css +0 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { withQuery } from "ufo";
|
|
2
|
+
import { useRegistryScript } from "#nuxt-scripts/utils";
|
|
3
|
+
import { object, string, optional, boolean } from "#nuxt-scripts-validator";
|
|
4
|
+
export const GoogleRecaptchaOptions = object({
|
|
5
|
+
siteKey: string(),
|
|
6
|
+
// Use enterprise.js instead of api.js
|
|
7
|
+
enterprise: optional(boolean()),
|
|
8
|
+
// Use recaptcha.net (works in China)
|
|
9
|
+
recaptchaNet: optional(boolean()),
|
|
10
|
+
// Language code
|
|
11
|
+
hl: optional(string())
|
|
12
|
+
});
|
|
13
|
+
export function useScriptGoogleRecaptcha(_options) {
|
|
14
|
+
return useRegistryScript(_options?.key || "googleRecaptcha", (options) => {
|
|
15
|
+
const baseUrl = options?.recaptchaNet ? "https://www.recaptcha.net/recaptcha" : "https://www.google.com/recaptcha";
|
|
16
|
+
const scriptPath = options?.enterprise ? "enterprise.js" : "api.js";
|
|
17
|
+
return {
|
|
18
|
+
scriptInput: {
|
|
19
|
+
src: withQuery(`${baseUrl}/${scriptPath}`, {
|
|
20
|
+
render: options?.siteKey,
|
|
21
|
+
hl: options?.hl
|
|
22
|
+
}),
|
|
23
|
+
crossorigin: false
|
|
24
|
+
},
|
|
25
|
+
schema: import.meta.dev ? GoogleRecaptchaOptions : void 0,
|
|
26
|
+
scriptOptions: {
|
|
27
|
+
use() {
|
|
28
|
+
return { grecaptcha: window.grecaptcha };
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
clientInit: import.meta.server ? void 0 : () => {
|
|
32
|
+
const w = window;
|
|
33
|
+
w.grecaptcha = w.grecaptcha || {};
|
|
34
|
+
const readyFn = function(cb) {
|
|
35
|
+
(w.___grecaptcha_cfg = w.___grecaptcha_cfg || {}).fns = (w.___grecaptcha_cfg.fns || []).concat([cb]);
|
|
36
|
+
};
|
|
37
|
+
w.grecaptcha.ready = w.grecaptcha.ready || readyFn;
|
|
38
|
+
if (options?.enterprise) {
|
|
39
|
+
w.grecaptcha.enterprise = w.grecaptcha.enterprise || {};
|
|
40
|
+
w.grecaptcha.enterprise.ready = w.grecaptcha.enterprise.ready || readyFn;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}, _options);
|
|
45
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
2
|
+
export interface CredentialResponse {
|
|
3
|
+
credential: string;
|
|
4
|
+
select_by: 'auto' | 'user' | 'user_1tap' | 'user_2tap' | 'btn' | 'btn_confirm' | 'btn_add_session' | 'btn_confirm_add_session';
|
|
5
|
+
clientId?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface IdConfiguration {
|
|
8
|
+
client_id: string;
|
|
9
|
+
auto_select?: boolean;
|
|
10
|
+
callback?: (response: CredentialResponse) => void;
|
|
11
|
+
login_uri?: string;
|
|
12
|
+
native_callback?: (response: CredentialResponse) => void;
|
|
13
|
+
cancel_on_tap_outside?: boolean;
|
|
14
|
+
prompt_parent_id?: string;
|
|
15
|
+
nonce?: string;
|
|
16
|
+
context?: 'signin' | 'signup' | 'use';
|
|
17
|
+
state_cookie_domain?: string;
|
|
18
|
+
ux_mode?: 'popup' | 'redirect';
|
|
19
|
+
allowed_parent_origin?: string | string[];
|
|
20
|
+
intermediate_iframe_close_callback?: () => void;
|
|
21
|
+
itp_support?: boolean;
|
|
22
|
+
login_hint?: string;
|
|
23
|
+
hd?: string;
|
|
24
|
+
use_fedcm_for_prompt?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface GsiButtonConfiguration {
|
|
27
|
+
type?: 'standard' | 'icon';
|
|
28
|
+
theme?: 'outline' | 'filled_blue' | 'filled_black';
|
|
29
|
+
size?: 'large' | 'medium' | 'small';
|
|
30
|
+
text?: 'signin_with' | 'signup_with' | 'continue_with' | 'signin';
|
|
31
|
+
shape?: 'rectangular' | 'pill' | 'circle' | 'square';
|
|
32
|
+
logo_alignment?: 'left' | 'center';
|
|
33
|
+
width?: string | number;
|
|
34
|
+
locale?: string;
|
|
35
|
+
click_listener?: () => void;
|
|
36
|
+
use_fedcm?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export type MomentType = 'display' | 'skipped' | 'dismissed';
|
|
39
|
+
export interface MomentNotification {
|
|
40
|
+
isDisplayMoment: () => boolean;
|
|
41
|
+
isDisplayed: () => boolean;
|
|
42
|
+
isNotDisplayed: () => boolean;
|
|
43
|
+
getNotDisplayedReason: () => 'browser_not_supported' | 'invalid_client' | 'missing_client_id' | 'opt_out_or_no_session' | 'secure_http_required' | 'suppressed_by_user' | 'unregistered_origin' | 'unknown_reason';
|
|
44
|
+
isSkippedMoment: () => boolean;
|
|
45
|
+
getSkippedReason: () => 'auto_cancel' | 'user_cancel' | 'tap_outside' | 'issuing_failed';
|
|
46
|
+
isDismissedMoment: () => boolean;
|
|
47
|
+
getDismissedReason: () => 'credential_returned' | 'cancel_called' | 'flow_restarted';
|
|
48
|
+
getMomentType: () => MomentType;
|
|
49
|
+
}
|
|
50
|
+
export interface RevocationResponse {
|
|
51
|
+
successful: boolean;
|
|
52
|
+
error?: string;
|
|
53
|
+
}
|
|
54
|
+
declare namespace google {
|
|
55
|
+
namespace accounts {
|
|
56
|
+
namespace id {
|
|
57
|
+
function initialize(config: IdConfiguration): void;
|
|
58
|
+
function prompt(momentListener?: (notification: MomentNotification) => void): void;
|
|
59
|
+
function renderButton(parent: HTMLElement, options: GsiButtonConfiguration): void;
|
|
60
|
+
function disableAutoSelect(): void;
|
|
61
|
+
function cancel(): void;
|
|
62
|
+
function revoke(hint: string, callback: (response: RevocationResponse) => void): void;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
type AccountsNamespace = typeof google.accounts;
|
|
67
|
+
export interface GoogleSignInApi {
|
|
68
|
+
accounts: AccountsNamespace;
|
|
69
|
+
}
|
|
70
|
+
export declare const GoogleSignInOptions: import("valibot").ObjectSchema<{
|
|
71
|
+
readonly clientId: import("valibot").StringSchema<undefined>;
|
|
72
|
+
readonly autoSelect: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
73
|
+
readonly context: import("valibot").OptionalSchema<import("valibot").UnionSchema<[import("valibot").LiteralSchema<"signin", undefined>, import("valibot").LiteralSchema<"signup", undefined>, import("valibot").LiteralSchema<"use", undefined>], undefined>, undefined>;
|
|
74
|
+
readonly useFedcmForPrompt: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
75
|
+
readonly cancelOnTapOutside: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
76
|
+
readonly uxMode: import("valibot").OptionalSchema<import("valibot").UnionSchema<[import("valibot").LiteralSchema<"popup", undefined>, import("valibot").LiteralSchema<"redirect", undefined>], undefined>, undefined>;
|
|
77
|
+
readonly loginUri: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
78
|
+
readonly itpSupport: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
79
|
+
readonly allowedParentOrigin: import("valibot").OptionalSchema<import("valibot").UnionSchema<[import("valibot").StringSchema<undefined>, import("valibot").ArraySchema<import("valibot").StringSchema<undefined>, undefined>], undefined>, undefined>;
|
|
80
|
+
readonly hd: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
81
|
+
}, undefined>;
|
|
82
|
+
export type GoogleSignInInput = RegistryScriptInput<typeof GoogleSignInOptions>;
|
|
83
|
+
export declare function useScriptGoogleSignIn<T extends GoogleSignInApi>(_options?: GoogleSignInInput): import("#nuxt-scripts/types").UseScriptContext<T>;
|
|
84
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { useRegistryScript } from "#nuxt-scripts/utils";
|
|
2
|
+
import { object, string, optional, boolean, array, union, literal } from "#nuxt-scripts-validator";
|
|
3
|
+
export const GoogleSignInOptions = object({
|
|
4
|
+
clientId: string(),
|
|
5
|
+
// Auto-select credentials if only one is available
|
|
6
|
+
autoSelect: optional(boolean()),
|
|
7
|
+
// Context for One Tap (signin, signup, or use)
|
|
8
|
+
context: optional(union([literal("signin"), literal("signup"), literal("use")])),
|
|
9
|
+
// FedCM API support (Privacy Sandbox) - mandatory from August 2025
|
|
10
|
+
useFedcmForPrompt: optional(boolean()),
|
|
11
|
+
// Cancel One Tap if user clicks outside
|
|
12
|
+
cancelOnTapOutside: optional(boolean()),
|
|
13
|
+
// UX mode: popup or redirect
|
|
14
|
+
uxMode: optional(union([literal("popup"), literal("redirect")])),
|
|
15
|
+
// Login URI for redirect flow
|
|
16
|
+
loginUri: optional(string()),
|
|
17
|
+
// ITP (Intelligent Tracking Prevention) support
|
|
18
|
+
itpSupport: optional(boolean()),
|
|
19
|
+
// Allowed parent origins for iframe embedding
|
|
20
|
+
allowedParentOrigin: optional(union([string(), array(string())])),
|
|
21
|
+
// Hosted domain - restrict to specific Google Workspace domain
|
|
22
|
+
hd: optional(string())
|
|
23
|
+
});
|
|
24
|
+
export function useScriptGoogleSignIn(_options) {
|
|
25
|
+
return useRegistryScript(_options?.key || "googleSignIn", () => {
|
|
26
|
+
return {
|
|
27
|
+
scriptInput: {
|
|
28
|
+
src: "https://accounts.google.com/gsi/client",
|
|
29
|
+
// Performance best practice: async + defer to prevent render blocking
|
|
30
|
+
defer: true,
|
|
31
|
+
// Google's script doesn't support CORS
|
|
32
|
+
crossorigin: false
|
|
33
|
+
},
|
|
34
|
+
schema: import.meta.dev ? GoogleSignInOptions : void 0,
|
|
35
|
+
scriptOptions: {
|
|
36
|
+
use() {
|
|
37
|
+
return {
|
|
38
|
+
accounts: window.google?.accounts
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
clientInit: import.meta.server ? void 0 : () => {
|
|
43
|
+
const w = window;
|
|
44
|
+
w.google = w.google || {};
|
|
45
|
+
w.google.accounts = w.google.accounts || {};
|
|
46
|
+
w.google.accounts.id = w.google.accounts.id || {};
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}, _options);
|
|
50
|
+
}
|
|
@@ -11,7 +11,7 @@ export type DataLayer = Array<DataLayerItem>;
|
|
|
11
11
|
*/
|
|
12
12
|
export interface DataLayerPush {
|
|
13
13
|
(...args: Parameters<GTag>): void;
|
|
14
|
-
(obj: Record<string, unknown>): void;
|
|
14
|
+
(obj: Record<string, unknown> | any[]): void;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Improved DataLayer API type with more precise methods
|
|
@@ -89,6 +89,8 @@ export declare const GoogleTagManagerOptions: import("valibot").ObjectSchema<{
|
|
|
89
89
|
readonly envName: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
90
90
|
/** Referrer policy for analytics requests */
|
|
91
91
|
readonly authReferrerPolicy: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
92
|
+
/** Default consent settings for GTM */
|
|
93
|
+
readonly defaultConsent: import("valibot").OptionalSchema<import("valibot").RecordSchema<import("valibot").StringSchema<undefined>, import("valibot").UnionSchema<[import("valibot").StringSchema<undefined>, import("valibot").NumberSchema<undefined>], undefined>, undefined>, undefined>;
|
|
92
94
|
}, undefined>;
|
|
93
95
|
export type GoogleTagManagerInput = RegistryScriptInput<typeof GoogleTagManagerOptions>;
|
|
94
96
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { withQuery } from "ufo";
|
|
2
2
|
import { useRegistryScript } from "#nuxt-scripts/utils";
|
|
3
|
-
import { object, string, optional, boolean, union, literal } from "#nuxt-scripts-validator";
|
|
3
|
+
import { object, string, optional, boolean, union, literal, record, number } from "#nuxt-scripts-validator";
|
|
4
4
|
export const GoogleTagManagerOptions = object({
|
|
5
5
|
/** GTM container ID (format: GTM-XXXXXX) */
|
|
6
6
|
id: string(),
|
|
@@ -21,10 +21,12 @@ export const GoogleTagManagerOptions = object({
|
|
|
21
21
|
/** Environment name for environment-specific container */
|
|
22
22
|
envName: optional(string()),
|
|
23
23
|
/** Referrer policy for analytics requests */
|
|
24
|
-
authReferrerPolicy: optional(string())
|
|
24
|
+
authReferrerPolicy: optional(string()),
|
|
25
|
+
/** Default consent settings for GTM */
|
|
26
|
+
defaultConsent: optional(record(string(), union([string(), number()])))
|
|
25
27
|
});
|
|
26
28
|
export function useScriptGoogleTagManager(options) {
|
|
27
|
-
|
|
29
|
+
const instance = useRegistryScript(
|
|
28
30
|
options?.key || "googleTagManager",
|
|
29
31
|
(opts) => {
|
|
30
32
|
const dataLayerName = opts?.l ?? opts?.dataLayer ?? "dataLayer";
|
|
@@ -54,11 +56,13 @@ export function useScriptGoogleTagManager(options) {
|
|
|
54
56
|
},
|
|
55
57
|
clientInit: import.meta.server ? void 0 : () => {
|
|
56
58
|
window[dataLayerName] = window[dataLayerName] || [];
|
|
57
|
-
function gtag() {
|
|
58
|
-
window[dataLayerName].push(
|
|
59
|
+
function gtag(...args) {
|
|
60
|
+
window[dataLayerName].push(args);
|
|
59
61
|
}
|
|
60
62
|
window.gtag = gtag;
|
|
61
63
|
options?.onBeforeGtmStart?.(gtag);
|
|
64
|
+
if (opts.defaultConsent)
|
|
65
|
+
gtag("consent", "default", opts.defaultConsent);
|
|
62
66
|
window[dataLayerName].push({
|
|
63
67
|
"gtm.start": (/* @__PURE__ */ new Date()).getTime(),
|
|
64
68
|
"event": "gtm.js"
|
|
@@ -68,4 +72,10 @@ export function useScriptGoogleTagManager(options) {
|
|
|
68
72
|
},
|
|
69
73
|
options
|
|
70
74
|
);
|
|
75
|
+
if (import.meta.client && options?.onBeforeGtmStart) {
|
|
76
|
+
const gtag = window.gtag;
|
|
77
|
+
if (gtag)
|
|
78
|
+
options.onBeforeGtmStart(gtag);
|
|
79
|
+
}
|
|
80
|
+
return instance;
|
|
71
81
|
}
|
|
@@ -46,7 +46,7 @@ export function useScriptMatomoAnalytics(_options) {
|
|
|
46
46
|
_paq.push(["disableCookies"]);
|
|
47
47
|
}
|
|
48
48
|
if (options?.trackerUrl || options?.matomoUrl) {
|
|
49
|
-
_paq.push(["setTrackerUrl", options?.trackerUrl
|
|
49
|
+
_paq.push(["setTrackerUrl", options?.trackerUrl ?? withBase(`/matomo.php`, options?.matomoUrl || "")]);
|
|
50
50
|
} else if (normalizedCloudId) {
|
|
51
51
|
_paq.push(["setTrackerUrl", withBase(`/matomo.php`, withHttps(normalizedCloudId))]);
|
|
52
52
|
}
|
|
@@ -74,13 +74,15 @@ export function useScriptPlausibleAnalytics(_options) {
|
|
|
74
74
|
use() {
|
|
75
75
|
return { plausible: window.plausible };
|
|
76
76
|
},
|
|
77
|
-
clientInit() {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
plausible.o = i || {};
|
|
77
|
+
clientInit: import.meta.server ? void 0 : () => {
|
|
78
|
+
const w = window;
|
|
79
|
+
w.plausible = w.plausible || function() {
|
|
80
|
+
(w.plausible.q = w.plausible.q || []).push(arguments);
|
|
82
81
|
};
|
|
83
|
-
|
|
82
|
+
w.plausible.init = w.plausible.init || function(i) {
|
|
83
|
+
w.plausible.o = i || {};
|
|
84
|
+
};
|
|
85
|
+
w.plausible.init(initOptions);
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { PostHog } from 'posthog-js';
|
|
2
|
+
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
3
|
+
export declare const PostHogOptions: import("valibot").ObjectSchema<{
|
|
4
|
+
readonly apiKey: import("valibot").StringSchema<undefined>;
|
|
5
|
+
readonly region: import("valibot").OptionalSchema<import("valibot").UnionSchema<[import("valibot").LiteralSchema<"us", undefined>, import("valibot").LiteralSchema<"eu", undefined>], undefined>, undefined>;
|
|
6
|
+
readonly autocapture: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
7
|
+
readonly capturePageview: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
8
|
+
readonly capturePageleave: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
9
|
+
readonly disableSessionRecording: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
10
|
+
readonly config: import("valibot").OptionalSchema<import("valibot").RecordSchema<import("valibot").StringSchema<undefined>, import("valibot").AnySchema, undefined>, undefined>;
|
|
11
|
+
}, undefined>;
|
|
12
|
+
export type PostHogInput = RegistryScriptInput<typeof PostHogOptions, false, true>;
|
|
13
|
+
export interface PostHogApi {
|
|
14
|
+
posthog: PostHog;
|
|
15
|
+
}
|
|
16
|
+
declare global {
|
|
17
|
+
interface Window {
|
|
18
|
+
posthog?: PostHog;
|
|
19
|
+
__posthogInitPromise?: Promise<PostHog | undefined>;
|
|
20
|
+
_posthogQueue?: {
|
|
21
|
+
prop: string | symbol;
|
|
22
|
+
args: any[];
|
|
23
|
+
}[];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export declare function useScriptPostHog<T extends PostHogApi>(_options?: PostHogInput): import("#nuxt-scripts/types").UseScriptContext<T>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { any, record, string, object, optional, boolean, union, literal } from "#nuxt-scripts-validator";
|
|
2
|
+
import { useRegistryScript } from "../utils.js";
|
|
3
|
+
import { logger } from "../logger.js";
|
|
4
|
+
export const PostHogOptions = object({
|
|
5
|
+
apiKey: string(),
|
|
6
|
+
region: optional(union([literal("us"), literal("eu")])),
|
|
7
|
+
autocapture: optional(boolean()),
|
|
8
|
+
capturePageview: optional(boolean()),
|
|
9
|
+
capturePageleave: optional(boolean()),
|
|
10
|
+
disableSessionRecording: optional(boolean()),
|
|
11
|
+
config: optional(record(string(), any()))
|
|
12
|
+
});
|
|
13
|
+
export function useScriptPostHog(_options) {
|
|
14
|
+
return useRegistryScript("posthog", (options) => {
|
|
15
|
+
return {
|
|
16
|
+
scriptMode: "npm",
|
|
17
|
+
// Use NPM mode - no external script tag
|
|
18
|
+
schema: import.meta.dev ? PostHogOptions : void 0,
|
|
19
|
+
scriptOptions: {
|
|
20
|
+
use() {
|
|
21
|
+
if (import.meta.server)
|
|
22
|
+
return { posthog: {} };
|
|
23
|
+
if (window.posthog)
|
|
24
|
+
return { posthog: window.posthog };
|
|
25
|
+
const posthog = new Proxy({}, {
|
|
26
|
+
get(_, prop) {
|
|
27
|
+
if (window.posthog)
|
|
28
|
+
return window.posthog[prop];
|
|
29
|
+
if (prop === "then")
|
|
30
|
+
return void 0;
|
|
31
|
+
return (...args) => {
|
|
32
|
+
if (window.posthog)
|
|
33
|
+
return window.posthog[prop](...args);
|
|
34
|
+
window._posthogQueue = window._posthogQueue || [];
|
|
35
|
+
window._posthogQueue.push({ prop, args });
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
return { posthog };
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
clientInit: import.meta.server ? void 0 : async () => {
|
|
43
|
+
if (window.__posthogInitPromise || window.posthog)
|
|
44
|
+
return;
|
|
45
|
+
if (!options?.apiKey) {
|
|
46
|
+
logger.warn("PostHog apiKey is required");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const region = options?.region || "us";
|
|
50
|
+
const apiHost = region === "eu" ? "https://eu.i.posthog.com" : "https://us.i.posthog.com";
|
|
51
|
+
console.log("[PostHog] Starting dynamic import of posthog-js...");
|
|
52
|
+
window.__posthogInitPromise = import("posthog-js").then(({ default: posthog }) => {
|
|
53
|
+
console.log("[PostHog] posthog-js imported successfully");
|
|
54
|
+
const config = {
|
|
55
|
+
api_host: apiHost,
|
|
56
|
+
...options?.config
|
|
57
|
+
};
|
|
58
|
+
if (typeof options?.autocapture === "boolean")
|
|
59
|
+
config.autocapture = options.autocapture;
|
|
60
|
+
if (typeof options?.capturePageview === "boolean")
|
|
61
|
+
config.capture_pageview = options.capturePageview;
|
|
62
|
+
if (typeof options?.capturePageleave === "boolean")
|
|
63
|
+
config.capture_pageleave = options.capturePageleave;
|
|
64
|
+
if (typeof options?.disableSessionRecording === "boolean")
|
|
65
|
+
config.disable_session_recording = options.disableSessionRecording;
|
|
66
|
+
console.log("[PostHog] Calling posthog.init with apiKey:", options.apiKey, "config:", config);
|
|
67
|
+
const instance = posthog.init(options.apiKey, config);
|
|
68
|
+
if (!instance) {
|
|
69
|
+
logger.error("PostHog init returned undefined - initialization failed");
|
|
70
|
+
delete window._posthogQueue;
|
|
71
|
+
return void 0;
|
|
72
|
+
}
|
|
73
|
+
console.log("[PostHog] posthog.init succeeded, instance:", instance);
|
|
74
|
+
window.posthog = instance;
|
|
75
|
+
if (window._posthogQueue && window._posthogQueue.length > 0) {
|
|
76
|
+
console.log("[PostHog] Flushing", window._posthogQueue.length, "queued calls");
|
|
77
|
+
window._posthogQueue.forEach((q) => window.posthog[q.prop]?.(...q.args));
|
|
78
|
+
delete window._posthogQueue;
|
|
79
|
+
}
|
|
80
|
+
console.log("[PostHog] Initialization complete!");
|
|
81
|
+
return window.posthog;
|
|
82
|
+
}).catch((e) => {
|
|
83
|
+
logger.error("Failed to load posthog-js:", e);
|
|
84
|
+
console.error("[PostHog] Import/init error:", e);
|
|
85
|
+
delete window._posthogQueue;
|
|
86
|
+
return void 0;
|
|
87
|
+
});
|
|
88
|
+
return window.__posthogInitPromise;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}, _options);
|
|
92
|
+
}
|
|
@@ -15,7 +15,39 @@ export const RybbitAnalyticsOptions = object({
|
|
|
15
15
|
debounce: optional(number()),
|
|
16
16
|
apiKey: optional(string())
|
|
17
17
|
});
|
|
18
|
+
const RYBBIT_QUEUE_KEY = Symbol.for("nuxt-scripts.rybbit-queue");
|
|
19
|
+
function getRybbitState() {
|
|
20
|
+
if (!import.meta.client) return;
|
|
21
|
+
const g = globalThis;
|
|
22
|
+
if (!g[RYBBIT_QUEUE_KEY]) {
|
|
23
|
+
g[RYBBIT_QUEUE_KEY] = { queue: [], flushed: false };
|
|
24
|
+
}
|
|
25
|
+
return g[RYBBIT_QUEUE_KEY];
|
|
26
|
+
}
|
|
18
27
|
export function useScriptRybbitAnalytics(_options) {
|
|
28
|
+
const isRybbitReady = () => import.meta.client && typeof window !== "undefined" && window.rybbit && typeof window.rybbit.event === "function";
|
|
29
|
+
const flushQueue = () => {
|
|
30
|
+
const state = getRybbitState();
|
|
31
|
+
if (!state || state.flushed || !isRybbitReady()) return;
|
|
32
|
+
state.flushed = true;
|
|
33
|
+
while (state.queue.length > 0) {
|
|
34
|
+
const [method, ...args] = state.queue.shift();
|
|
35
|
+
const fn = window.rybbit[method];
|
|
36
|
+
if (typeof fn === "function") {
|
|
37
|
+
fn.apply(window.rybbit, args);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const callOrQueue = (method, ...args) => {
|
|
42
|
+
if (isRybbitReady()) {
|
|
43
|
+
const fn = window.rybbit[method];
|
|
44
|
+
if (typeof fn === "function") {
|
|
45
|
+
fn.apply(window.rybbit, args);
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
getRybbitState()?.queue.push([method, ...args]);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
19
51
|
return useRegistryScript("rybbitAnalytics", (options) => {
|
|
20
52
|
return {
|
|
21
53
|
scriptInput: {
|
|
@@ -36,15 +68,13 @@ export function useScriptRybbitAnalytics(_options) {
|
|
|
36
68
|
schema: import.meta.dev ? RybbitAnalyticsOptions : void 0,
|
|
37
69
|
scriptOptions: {
|
|
38
70
|
use() {
|
|
39
|
-
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
71
|
+
flushQueue();
|
|
42
72
|
return {
|
|
43
|
-
pageview:
|
|
44
|
-
event:
|
|
45
|
-
identify:
|
|
46
|
-
clearUserId:
|
|
47
|
-
getUserId: window.rybbit
|
|
73
|
+
pageview: () => callOrQueue("pageview"),
|
|
74
|
+
event: (name, properties) => callOrQueue("event", name, properties),
|
|
75
|
+
identify: (userId) => callOrQueue("identify", userId),
|
|
76
|
+
clearUserId: () => callOrQueue("clearUserId"),
|
|
77
|
+
getUserId: () => window.rybbit?.getUserId?.() ?? null,
|
|
48
78
|
rybbit: window.rybbit
|
|
49
79
|
};
|
|
50
80
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
2
|
+
type StandardEvents = 'ViewContent' | 'ClickButton' | 'Search' | 'AddToWishlist' | 'AddToCart' | 'InitiateCheckout' | 'AddPaymentInfo' | 'CompletePayment' | 'PlaceAnOrder' | 'Contact' | 'Download' | 'SubmitForm' | 'CompleteRegistration' | 'Subscribe';
|
|
3
|
+
interface EventProperties {
|
|
4
|
+
content_id?: string;
|
|
5
|
+
content_type?: string;
|
|
6
|
+
content_name?: string;
|
|
7
|
+
contents?: Array<{
|
|
8
|
+
content_id: string;
|
|
9
|
+
content_type?: string;
|
|
10
|
+
content_name?: string;
|
|
11
|
+
price?: number;
|
|
12
|
+
quantity?: number;
|
|
13
|
+
}>;
|
|
14
|
+
currency?: string;
|
|
15
|
+
value?: number;
|
|
16
|
+
description?: string;
|
|
17
|
+
query?: string;
|
|
18
|
+
[key: string]: any;
|
|
19
|
+
}
|
|
20
|
+
interface IdentifyProperties {
|
|
21
|
+
email?: string;
|
|
22
|
+
phone_number?: string;
|
|
23
|
+
external_id?: string;
|
|
24
|
+
}
|
|
25
|
+
type TtqFns = ((cmd: 'track', event: StandardEvents | string, properties?: EventProperties) => void) & ((cmd: 'page') => void) & ((cmd: 'identify', properties: IdentifyProperties) => void) & ((cmd: string, ...args: any[]) => void);
|
|
26
|
+
export interface TikTokPixelApi {
|
|
27
|
+
ttq: TtqFns & {
|
|
28
|
+
push: TtqFns;
|
|
29
|
+
loaded: boolean;
|
|
30
|
+
queue: any[];
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
declare global {
|
|
34
|
+
interface Window extends TikTokPixelApi {
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export declare const TikTokPixelOptions: import("valibot").ObjectSchema<{
|
|
38
|
+
readonly id: import("valibot").StringSchema<undefined>;
|
|
39
|
+
readonly trackPageView: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
40
|
+
}, undefined>;
|
|
41
|
+
export type TikTokPixelInput = RegistryScriptInput<typeof TikTokPixelOptions, true, false, false>;
|
|
42
|
+
export declare function useScriptTikTokPixel<T extends TikTokPixelApi>(_options?: TikTokPixelInput): import("#nuxt-scripts/types").UseScriptContext<T>;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { withQuery } from "ufo";
|
|
2
|
+
import { useRegistryScript } from "../utils.js";
|
|
3
|
+
import { object, string, optional, boolean } from "#nuxt-scripts-validator";
|
|
4
|
+
export const TikTokPixelOptions = object({
|
|
5
|
+
id: string(),
|
|
6
|
+
trackPageView: optional(boolean())
|
|
7
|
+
// default true
|
|
8
|
+
});
|
|
9
|
+
export function useScriptTikTokPixel(_options) {
|
|
10
|
+
return useRegistryScript("tiktokPixel", (options) => ({
|
|
11
|
+
scriptInput: {
|
|
12
|
+
src: withQuery("https://analytics.tiktok.com/i18n/pixel/events.js", {
|
|
13
|
+
sdkid: options?.id,
|
|
14
|
+
lib: "ttq"
|
|
15
|
+
}),
|
|
16
|
+
crossorigin: false
|
|
17
|
+
},
|
|
18
|
+
schema: import.meta.dev ? TikTokPixelOptions : void 0,
|
|
19
|
+
scriptOptions: {
|
|
20
|
+
use() {
|
|
21
|
+
return { ttq: window.ttq };
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
clientInit: import.meta.server ? void 0 : () => {
|
|
25
|
+
const ttq = window.ttq = function(...params) {
|
|
26
|
+
if (ttq.callMethod) {
|
|
27
|
+
ttq.callMethod(...params);
|
|
28
|
+
} else {
|
|
29
|
+
ttq.queue.push(params);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
ttq.push = ttq;
|
|
33
|
+
ttq.loaded = true;
|
|
34
|
+
ttq.queue = [];
|
|
35
|
+
if (options?.id) {
|
|
36
|
+
ttq("init", options.id);
|
|
37
|
+
if (options?.trackPageView !== false) {
|
|
38
|
+
ttq("page");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}), _options);
|
|
43
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { createError, defineEventHandler, getHeader, getQuery, setHeader } from "h3";
|
|
2
|
+
import { $fetch } from "ofetch";
|
|
3
|
+
import { withQuery } from "ufo";
|
|
4
|
+
import { useRuntimeConfig } from "#imports";
|
|
5
|
+
export default defineEventHandler(async (event) => {
|
|
6
|
+
const runtimeConfig = useRuntimeConfig();
|
|
7
|
+
const publicConfig = runtimeConfig.public["nuxt-scripts"]?.googleStaticMapsProxy;
|
|
8
|
+
const privateConfig = runtimeConfig["nuxt-scripts"]?.googleStaticMapsProxy;
|
|
9
|
+
if (!publicConfig?.enabled) {
|
|
10
|
+
throw createError({
|
|
11
|
+
statusCode: 404,
|
|
12
|
+
statusMessage: "Google Static Maps proxy is not enabled"
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
const apiKey = privateConfig?.apiKey;
|
|
16
|
+
if (!apiKey) {
|
|
17
|
+
throw createError({
|
|
18
|
+
statusCode: 500,
|
|
19
|
+
statusMessage: "Google Maps API key not configured for proxy"
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const referer = getHeader(event, "referer");
|
|
23
|
+
const host = getHeader(event, "host");
|
|
24
|
+
if (referer && host) {
|
|
25
|
+
const refererUrl = new URL(referer).host;
|
|
26
|
+
if (refererUrl !== host) {
|
|
27
|
+
throw createError({
|
|
28
|
+
statusCode: 403,
|
|
29
|
+
statusMessage: "Invalid referer"
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const query = getQuery(event);
|
|
34
|
+
const { key: _clientKey, ...safeQuery } = query;
|
|
35
|
+
const googleMapsUrl = withQuery("https://maps.googleapis.com/maps/api/staticmap", {
|
|
36
|
+
...safeQuery,
|
|
37
|
+
key: apiKey
|
|
38
|
+
});
|
|
39
|
+
const response = await $fetch.raw(googleMapsUrl, {
|
|
40
|
+
headers: {
|
|
41
|
+
"User-Agent": "Nuxt Scripts Google Static Maps Proxy"
|
|
42
|
+
}
|
|
43
|
+
}).catch((error) => {
|
|
44
|
+
throw createError({
|
|
45
|
+
statusCode: error.statusCode || 500,
|
|
46
|
+
statusMessage: error.statusMessage || "Failed to fetch static map"
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
const cacheMaxAge = publicConfig.cacheMaxAge || 3600;
|
|
50
|
+
setHeader(event, "Content-Type", response.headers.get("content-type") || "image/png");
|
|
51
|
+
setHeader(event, "Cache-Control", `public, max-age=${cacheMaxAge}, s-maxage=${cacheMaxAge}`);
|
|
52
|
+
setHeader(event, "Vary", "Accept-Encoding");
|
|
53
|
+
return response._data;
|
|
54
|
+
});
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -29,8 +29,17 @@ import type { UmamiAnalyticsInput } from './registry/umami-analytics.js';
|
|
|
29
29
|
import type { RybbitAnalyticsInput } from './registry/rybbit-analytics.js';
|
|
30
30
|
import type { RedditPixelInput } from './registry/reddit-pixel.js';
|
|
31
31
|
import type { PayPalInput } from './registry/paypal.js';
|
|
32
|
+
import type { PostHogInput } from './registry/posthog.js';
|
|
33
|
+
import type { GoogleRecaptchaInput } from './registry/google-recaptcha.js';
|
|
34
|
+
import type { TikTokPixelInput } from './registry/tiktok-pixel.js';
|
|
32
35
|
export type WarmupStrategy = false | 'preload' | 'preconnect' | 'dns-prefetch';
|
|
33
|
-
export type UseScriptContext<T extends Record<symbol | string, any>> = VueScriptInstance<T
|
|
36
|
+
export type UseScriptContext<T extends Record<symbol | string, any>> = VueScriptInstance<T> & {
|
|
37
|
+
/**
|
|
38
|
+
* Remove and reload the script. Useful for scripts that need to re-execute
|
|
39
|
+
* after SPA navigation (e.g., DOM-scanning scripts like iubenda).
|
|
40
|
+
*/
|
|
41
|
+
reload: () => Promise<T>;
|
|
42
|
+
};
|
|
34
43
|
export type NuxtUseScriptOptions<T extends Record<symbol | string, any> = {}> = Omit<UseScriptOptions<T>, 'trigger'> & {
|
|
35
44
|
/**
|
|
36
45
|
* The trigger to load the script:
|
|
@@ -135,16 +144,19 @@ export interface ScriptRegistry {
|
|
|
135
144
|
googleAdsense?: GoogleAdsenseInput;
|
|
136
145
|
googleAnalytics?: GoogleAnalyticsInput;
|
|
137
146
|
googleMaps?: GoogleMapsInput;
|
|
147
|
+
googleRecaptcha?: GoogleRecaptchaInput;
|
|
138
148
|
lemonSqueezy?: LemonSqueezyInput;
|
|
139
149
|
googleTagManager?: GoogleTagManagerInput;
|
|
140
150
|
hotjar?: HotjarInput;
|
|
141
151
|
intercom?: IntercomInput;
|
|
142
152
|
paypal?: PayPalInput;
|
|
153
|
+
posthog?: PostHogInput;
|
|
143
154
|
matomoAnalytics?: MatomoAnalyticsInput;
|
|
144
155
|
rybbitAnalytics?: RybbitAnalyticsInput;
|
|
145
156
|
redditPixel?: RedditPixelInput;
|
|
146
157
|
segment?: SegmentInput;
|
|
147
158
|
stripe?: StripeInput;
|
|
159
|
+
tiktokPixel?: TikTokPixelInput;
|
|
148
160
|
xPixel?: XPixelInput;
|
|
149
161
|
snapchatPixel?: SnapTrPixelInput;
|
|
150
162
|
youtubePlayer?: YouTubePlayerInput;
|
package/dist/runtime/utils.d.ts
CHANGED
|
@@ -10,7 +10,8 @@ type OptionsFn<O> = (options: InferIfSchema<O>, ctx: {
|
|
|
10
10
|
scriptInput?: UseScriptInput;
|
|
11
11
|
scriptOptions?: NuxtUseScriptOptions;
|
|
12
12
|
schema?: O extends ObjectSchema<any, any> ? O : undefined;
|
|
13
|
-
clientInit?: () => void
|
|
13
|
+
clientInit?: () => void | Promise<any>;
|
|
14
|
+
scriptMode?: 'external' | 'npm';
|
|
14
15
|
});
|
|
15
16
|
export declare function scriptRuntimeConfig<T extends keyof ScriptRegistry>(key: T): ScriptRegistry[T];
|
|
16
17
|
export declare function useRegistryScript<T extends Record<string | symbol, any>, O = EmptyOptionsSchema>(registryKey: keyof ScriptRegistry | string, optionsFn: OptionsFn<O>, _userOptions?: RegistryScriptInput<O>): UseScriptContext<UseFunctionType<NuxtUseScriptOptions<T>, T>>;
|