import {z} from 'zod' export type TrackingConfigWriteVersion = 1; export type StoreGooglePurchaseSelection = {destination_id: string, action_id: string}; export type TrackingAssets = {fb?: Array | undefined, tiktok?: Array | undefined, kwai_client?: Array | undefined, kwai_server?: Array | undefined, google_ads?: Array | undefined, gtm?: Array | undefined}; export type TrackingEvent = {provider: 'fb' | 'tiktok' | 'kwai_client' | 'kwai_server' | 'google_ads' | 'gtm', name: string, legacy_purchase?: true | undefined, legacy_renderer?: ('vue' | 'html') | undefined, legacy_null_parameters?: true | undefined, initialization?: true | undefined, legacy_document_only?: true | undefined, legacy_document_server_only?: true | undefined, channels?: (Array<'browser' | 'server'>) | undefined, parameters?: {[key: string]: unknown} | undefined, parameter_variants?: ({vue_browser?: {[key: string]: unknown} | undefined, vue_server?: {[key: string]: unknown} | undefined, html_browser?: {[key: string]: unknown} | undefined, html_server?: {[key: string]: unknown} | undefined}) | undefined, asset_ids?: (Array) | undefined, destination_id?: string | undefined, action_id?: string | undefined, kind?: 'remarketing' | undefined, tag_id?: string | undefined, conversion_label?: string | undefined}; export type TrackingConfig = {purchase?: ({google_ads?: Array | undefined}) | undefined, schema_version: 1, assets: TrackingAssets, context_assets?: {[key: string]: TrackingAssets} | undefined, triggers: Array<{id: string, context: string, trigger: 'page_open' | 'product_view' | 'search' | 'cart_add' | 'checkout_start' | 'form_submit' | 'widget_click' | 'payment_methods_opened' | 'payment_method_selected' | 'banner_click', events: Array}>}; export type HtmlModeDocument = string | null; export type HtmlModeCspPolicy = {connect_src?: Array | undefined, img_src?: Array | undefined, script_src?: Array | undefined, style_src?: Array | undefined, frame_src?: Array | undefined}; export type LandingPageDisplayVersionRequest = {tracking_config_write_version: TrackingConfigWriteVersion, tracking_config?: TrackingConfig | undefined, tracking_config_revision?: string | undefined, render_mode?: unknown, html_document?: HtmlModeDocument | undefined, html_code?: unknown, css_code?: unknown, js_code?: unknown, additional_head_code?: unknown, csp_policy?: HtmlModeCspPolicy | undefined, meta?: unknown, form_display?: unknown, google_ads_destination_ids?: Array | undefined, fb_pixel_ids?: unknown, tiktok_pixel_ids?: unknown, kwai_client_pixel_ids?: unknown, kwai_server_pixel_ids?: unknown, onload_fb_events?: unknown, onload_tiktok_events?: unknown, onload_kwai_client_events?: unknown, onload_kwai_server_events?: unknown, fb_events_onload_parameters?: unknown, tiktok_events_onload_parameters?: unknown, kwai_client_events_onload_parameters?: unknown, kwai_server_events_onload_parameters?: unknown} | {[key: string]: unknown}; export type CreateApiV3PagesPageIdPageDisplaysArgs = {body: LandingPageDisplayVersionRequest}; export type CreateApiV3PagesPageIdPageDisplaysOptions = {baseUrl?: string | undefined, bearerAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const storeGooglePurchaseSelection = z.object({destination_id: z.string(), action_id: z.string()}); export const trackingAssets = z.object({fb: z.array(z.number().int().gte(1)).optional(), tiktok: z.array(z.number().int().gte(1)).optional(), kwai_client: z.array(z.number().int().gte(1)).optional(), kwai_server: z.array(z.number().int().gte(1)).optional(), google_ads: z.array(z.string()).optional(), gtm: z.array(z.number().int().gte(1)).optional()}); export const trackingEvent = z.object({provider: z.enum(["fb", "tiktok", "kwai_client", "kwai_server", "google_ads", "gtm"]), name: z.string().min(1).max(100), legacy_purchase: z.literal(true).optional(), legacy_renderer: z.enum(["vue", "html"]).optional(), legacy_null_parameters: z.literal(true).optional(), initialization: z.literal(true).optional(), legacy_document_only: z.literal(true).optional(), legacy_document_server_only: z.literal(true).optional(), channels: z.array(z.enum(["browser", "server"])).optional(), parameters: z.record(z.string(), z.unknown()).optional(), parameter_variants: z.object({vue_browser: z.record(z.string(), z.unknown()).optional(), vue_server: z.record(z.string(), z.unknown()).optional(), html_browser: z.record(z.string(), z.unknown()).optional(), html_server: z.record(z.string(), z.unknown()).optional()}).optional(), asset_ids: z.array(z.union([z.number().int(), z.string()])).optional(), destination_id: z.string().optional(), action_id: z.string().optional(), kind: z.literal("remarketing").optional(), tag_id: z.string().optional(), conversion_label: z.string().optional()}); export const trackingConfig = z.object({purchase: z.object({google_ads: z.array(storeGooglePurchaseSelection).optional()}).optional(), schema_version: z.literal(1), assets: trackingAssets, context_assets: z.record(z.string(), trackingAssets).optional(), triggers: z.array(z.object({id: z.string().min(1).max(200), context: z.string().max(250), trigger: z.enum(["page_open", "product_view", "search", "cart_add", "checkout_start", "form_submit", "widget_click", "payment_methods_opened", "payment_method_selected", "banner_click"]), events: z.array(trackingEvent)}))}); export const htmlModeDocument = z.string().nullable(); export const htmlModeCspPolicy = z.object({connect_src: z.array(z.string()).optional(), img_src: z.array(z.string()).optional(), script_src: z.array(z.string()).optional(), style_src: z.array(z.string()).optional(), frame_src: z.array(z.string()).optional()}); export const checkoutOrderBump = z.object({key: z.string(), enabled: z.boolean(), available: z.boolean().optional(), type: z.enum(["variant", "bundle"]), variant_id: z.number().int().nullable().optional(), bundle_price_option_id: z.number().int().nullable().optional(), title: z.string().max(500).optional(), description: z.string().max(5000).optional(), images: z.array(z.string().max(500)).optional(), auto_check: z.boolean().optional(), shown: z.boolean().optional(), toggle_position: z.enum(["top", "bottom"]).optional(), image_autoslide: z.boolean().optional(), image_duration: z.number().int().gte(0).lte(3600).optional(), variant: z.record(z.string(), z.unknown()).nullable().optional(), bundle_price_option: z.record(z.string(), z.unknown()).nullable().optional()}); export const landingPageFormDisplay = z.object({is_sending_email_invoice: z.boolean().optional(), order_bumps: z.array(checkoutOrderBump).nullable().optional(), form_position: z.array(z.string()).optional(), id: z.number().int().optional(), store: z.record(z.string(), z.unknown()).nullable().optional(), variants: z.array(z.record(z.string(), z.unknown())).optional(), bundle_price_options: z.array(z.record(z.string(), z.unknown())).optional(), after_submit_event: z.string().optional(), handler_assignment: z.string().optional(), store_sales_person: z.record(z.string(), z.unknown()).nullable().optional(), custom_phone: z.string().optional(), other_page: z.record(z.string(), z.unknown()).nullable().optional(), custom_url: z.string().optional(), onsubmit_fb_events: z.array(z.string()).optional(), onsubmit_tiktok_events: z.array(z.string()).optional(), onsubmit_kwai_client_events: z.array(z.string()).optional(), onsubmit_kwai_server_events: z.array(z.string()).optional()}).and(z.record(z.string(), z.unknown())); export const landingPageDisplay = z.object({tracking_form_delivery: z.literal("server_v1").optional(), tracking_config: trackingConfig.nullable().optional(), tracking_config_revision: z.string().nullable().optional(), tracking_config_error: z.string().nullable().optional(), tracking_context: z.string().optional(), id: z.number().int().optional(), version: z.number().int().optional(), schema_version: z.number().int().optional(), created_at: z.string().optional(), created_by_id: z.number().int().nullable().optional(), is_published: z.boolean().optional(), published_at: z.string().nullable().optional(), render_mode: z.enum(["html_mode", "builder"]).optional(), html_document: htmlModeDocument.optional(), html_code: z.string().nullable().optional(), css_code: z.string().nullable().optional(), js_code: z.string().nullable().optional(), additional_head_code: z.string().nullable().optional(), csp_policy: htmlModeCspPolicy.optional(), form_display: landingPageFormDisplay.nullable().optional(), fb_pixels: z.array(z.record(z.string(), z.unknown())).optional(), tiktok_pixels: z.array(z.record(z.string(), z.unknown())).optional(), kwai_client_pixels: z.array(z.record(z.string(), z.unknown())).optional(), kwai_server_pixels: z.array(z.record(z.string(), z.unknown())).optional()}).and(z.record(z.string(), z.unknown())); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Create a landing page display * * POST /v3/pages/{page_id}/page-displays * * Also accepts auth: apiKeyAuth, scalevOAuth */ export const createApiV3PagesPageIdPageDisplays = async (args: CreateApiV3PagesPageIdPageDisplaysArgs, options?: CreateApiV3PagesPageIdPageDisplaysOptions) => { const {baseUrl = "https://api.scalev.com", fetch: fetchFn = fetch, bearerAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (bearerAuth !== undefined) headers.set('authorization', `Bearer ${bearerAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/v3/pages/${encodeURIComponent(String(args.page_id))}/page-displays${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(landingPageDisplay, await res.json()) };