@clakta/nextjs

中文文档
1.1.4发布于 2026/11/01MITTypeScriptESM + CJS

@clakta/nextjs

原始使用文档
文档目录12 节
  1. Installation
  2. Usage
  3. App Router
  4. Pages Router
  5. Props
  6. Tracking events
  7. Identifying customers
  8. Ecommerce
  9. Consent
  10. API
  11. Links
  12. License

@clakta/nextjs

The official Clakta SDK for Next.js.

Clakta is a modern sales and ads tracking platform built for modern businesses. Get accurate data and know which ads perform best, which influencer sells the most, with a modern and powerful platform.

Website

npm version npm downloads minzipped size license


Wraps @clakta/javascript with a <ClaktaProvider> component that initializes the SDK once on mount. Works with both the App Router and the Pages Router.

Requires Next.js 13+ and React 18+.

Installation

npm install @clakta/nextjs
pnpm add @clakta/nextjs
yarn add @clakta/nextjs

Usage

Render <ClaktaProvider> once near the root of your app and pass your script id. It renders nothing, and initialization runs exactly once for the lifetime of the page.

App Router

// app/layout.tsx
import { ClaktaProvider } from "@clakta/nextjs"

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        <ClaktaProvider id="YOUR_SCRIPT_ID" />
        {children}
      </body>
    </html>
  )
}

The provider is already a client component, so you don't need "use client" in your layout.

Pages Router

// pages/_app.tsx
import { ClaktaProvider } from "@clakta/nextjs"
import type { AppProps } from "next/app"

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <ClaktaProvider id="YOUR_SCRIPT_ID" />
      <Component {...pageProps} />
    </>
  )
}

Props

<ClaktaProvider> takes the same options as init:

PropTypeDefaultDescription
idstring—Required. Your Clakta script id.
apiHoststringhttps://api.clakta.comOverride the API host. Tracking/config use https://t.clakta.com by default; Stripe stays on api.clakta.com.
debugbooleanfalseVerbose console logging.
consentbooleanby visitor locationWhether the visitor has consented to first-party identifiers. See Consent.

Because initialization happens once per page lifetime, prop changes after the first mount are ignored — except consent, which is applied as updateConsent would. Pass the id from an env var rather than from state:

<ClaktaProvider id={process.env.NEXT_PUBLIC_CLAKTA_ID!} />

Tracking events

Page views are handled for you when they're enabled for your project — App Router and Pages Router navigations both go through the History API, which the SDK listens to. Everything else you call directly.

Tracking functions touch window, so call them from client components — in an event handler or an effect, never during a server render.

"use client"

import { trackEvent } from "@clakta/nextjs"

export function BuyButton() {
  return (
    <button onClick={() => trackEvent("hero-cta", "click", { variant: "A" })}>
      Buy now
    </button>
  )
}

Identifying customers

"use client"

import { identify } from "@clakta/nextjs"
import { useEffect } from "react"

export function IdentifyUser({
  user,
}: {
  user: { id: string; email: string }
}) {
  useEffect(() => {
    identify({ externalId: user.id, email: user.email })
  }, [user])

  return null
}

At least one of externalId, claktaCustomerId, or email is required.

Ecommerce

Three funnel events cover the path to a sale. They touch window, so call them from client components.

"use client"

import { addToCart, initiateCheckout, purchase } from "@clakta/nextjs"

// Add to cart — no order exists yet
addToCart({
  products: [{ id: "42", name: "Tee", price: 29.99, quantity: 2 }],
  totalPrice: 59.98,
  currency: "USD",
})

// Checkout started
initiateCheckout({
  orderId: "1001",
  totalPrice: 59.98,
  currency: "USD",
  products: [{ id: "42", name: "Tee", price: 29.99, quantity: 2 }],
  customer: { email: "[email protected]" },
})

// Purchase completed
purchase({
  orderId: "1001",
  totalPrice: 59.98,
  currency: "USD",
  paymentMethod: "credit_card",
  products: [{ id: "42", name: "Tee", price: 29.99, quantity: 2 }],
  customer: { email: "[email protected]" },
  // Optional — clkt is read from the URL when you don't pass one
  tracking: { utm_source: "facebook", utm_medium: "cpc" },
})

initiateCheckout and purchase require orderId — the order's id in your own database, and the same value your server sends to the Orders API. Calls without one are dropped with a console warning.

Clakta reconciles the browser event against the order your server posts, and the server's order stays the source of truth for status, totals and contents — so a visitor who closes the tab before your thank-you page renders costs you nothing. Everything besides orderId is a small identifying subset of that payload (totalPrice, currency, paymentMethod, products, customer, tracking); fields the server owns aren't accepted from the client.

customer is personal data and is sent only under full_attribution with consent granted. See the @clakta/javascript README for the full field reference.

Both events also take an optional tracking block — clkt plus utm_source, utm_medium, utm_campaign and utm_content — that credits the order to a click. Omit clkt and the SDK resolves it from the current URL, falling back to the URL the visit landed on, which matters in the App Router: the confirmation page you redirect to no longer carries the ad's query string.

A common shape in the App Router — fire the purchase event from the confirmation page, once, with the order id you already have server-side:

// app/orders/[orderId]/confirmation/page.tsx
import { PurchaseTracker } from "./purchase-tracker"

export default async function ConfirmationPage({
  params,
}: {
  params: Promise<{ orderId: string }>
}) {
  const { orderId } = await params
  const order = await getOrder(orderId) // your own data layer

  return (
    <>
      <PurchaseTracker order={order} />
      <OrderSummary order={order} />
    </>
  )
}
// app/orders/[orderId]/confirmation/purchase-tracker.tsx
"use client"

import { purchase } from "@clakta/nextjs"
import { useEffect, useRef } from "react"

export function PurchaseTracker({ order }: { order: Order }) {
  const tracked = useRef(false)

  useEffect(() => {
    if (tracked.current) return
    tracked.current = true

    purchase({
      orderId: order.id,
      totalPrice: order.total,
      currency: order.currency,
      paymentMethod: "credit_card",
      products: order.items.map((item) => ({
        id: item.productId,
        name: item.name,
        quantity: item.quantity,
        price: item.price,
      })),
      customer: { email: order.customerEmail },
    })
  }, [order])

  return null
}

Consent only has an effect when your project runs in full_attribution mode; in privacy_friendly mode no first-party identifiers are ever used.

Unless you set it, consent follows where the visitor is: visitors in the EU, the EEA, the UK and Switzerland — and any visitor whose location is unknown — start without it and are only identified once your cookie banner grants it. Everyone else starts with it. A visitor without consent is still counted, anonymously. See the @clakta/javascript README for exactly what is and isn't collected.

Set it on the provider — false to keep every visitor anonymous until they accept on the page, wherever they are and whatever they answered before, or true if the provider only renders once the visitor has accepted:

<ClaktaProvider id="YOUR_SCRIPT_ID" consent={false} />

The prop stays live after mount, so you can drive it from your banner's state. Or update it directly when the visitor answers:

"use client"

import { updateConsent } from "@clakta/nextjs"

export function CookieBanner() {
  return <button onClick={() => updateConsent(true)}>Accept</button>
}

Read the current state with getConsent, which reports false until a choice is made:

import { getConsent } from "@clakta/nextjs"

getConsent() // => true

The answer is remembered — in a cookie for a year, and in localStorage with no expiry — so later pages apply it from their first event, and a visitor who accepts mid-visit starts an identified session right away that keeps the ad source they arrived with. Revoking consent immediately clears every identifier the SDK stored, and subsequent events are recorded anonymously.

API

Re-exported from @clakta/javascript, so you only need one dependency for the common cases:

init · pageView · trackEvent · identify · pageViewWithProduct · addToCart · initiateCheckout · purchase · getConsent · updateConsent

Plus the types: ClaktaCartDetails, ClaktaConfig, ClaktaOptions, ClaktaOrderCustomer, ClaktaOrderDetails, ClaktaPaymentMethod, ClaktaProduct, ClaktaTrackingParams, CustomerData, ResolvedConfig, TrackingMode.

See the @clakta/javascript README for the full API reference, tracking modes, and automatic-tracking behavior.

License

MIT

版本与发布记录

@clakta/nextjs 共发布 4 个版本,首次发布于 2026/10/22;过去 12 个月发布了 4 个版本。

版本发布日期距今
1.1.4latest2026/11/012 天前
1.1.32026/10/268 天前
1.1.22026/10/2211 天前
0.0.0-stage2026/10/2211 天前

关于 @clakta/nextjs 的常见问题

@clakta/nextjs 是什么?

@clakta / nextjs

如何安装 @clakta/nextjs?

在项目目录运行 npm install @clakta/nextjs,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:next(>=13.0.0)、react(>=18.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@clakta/nextjs 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@clakta/nextjs 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@clakta/nextjs 可以商用吗?

@clakta/nextjs 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@clakta/nextjs 还在维护吗?

最新版本 1.1.4 发布于 2026/11/01(2 天前);至今共发布 4 个版本,其中过去 12 个月发布了 4 个;首次发布于 2026/10/22。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。