Использование OpenReplay с Next.js
Заставить трекер работать в приложении на Next.js довольно просто. Поскольку Next.js работает поверх React, процесс во многом аналогичен; основная сложность связана с возможностями рендеринга на стороне сервера (Server Side Rendering) в Next.js.
Но как только вы поймёте, как они работают и как структурировать код, предназначенный только для клиента, вы сможете отслеживать своих пользователей в мгновение ока.
Добавление кода отслеживания
Section titled Добавление кода отслеживанияХотя при создании нового проекта вы можете получить версию кода для копирования и вставки прямо с платформы, этот код слишком примитивен и может не соответствовать передовым практикам, ожидаемым вашей командой или компанией.
Компонент Tracker
Section titled Компонент TrackerЭтот метод предлагает минималистичный подход, при котором мы внедряем трекер в приложение в виде компонента, который будет динамически загружать библиотеку.
App Router (v14+) - use client
Section titled App Router (v14+) - use client'use client'
import { useEffect } from "react"
// note that you can manually import Tracker class if you want to handle the instance manually
import { tracker } from '@openreplay/tracker'
tracker.configure({
projectKey: PROJECT_KEY,
ingestPoint: "https://openreplay.mydomain.com/ingest", // when dealing with the self-hosted version of OpenReplay
})
const Openreplay = () => {
useEffect(() => {
if (typeof window !== 'undefined') {
tracker.start()
}
}, [])
return null
}
export default Openreplay
App Router - динамический импорт экземпляра компонента Openreplay в корневой layout
Section titled App Router - динамический импорт экземпляра компонента Openreplay в корневой layoutimport dynamic from "next/dynamic";
const OpenReplayNoSSR = dynamic(() => import('//import the Openreplay instance'), {
ssr: false, //disables Server-side pre-rendering so window won't be undefined
})
export default function RootLayout({ children }) {
return (
<html lang="en" >
<body>
{children}
<OpenReplayNoSSR />
</body>
</html >
);
}
Обычный компонент (Next до версии v13)
Section titled Обычный компонент (Next до версии v13)[...]
function TrackerComponent() {
const [tracker, setTracker] = React.useState(null);
React.useEffect(() => {
(async function () {
const { tracker } = await import("@openreplay/tracker");
tracker.configure({
projectKey: PROJECT_KEY,
ingestPoint: "https://openreplay.mydomain.com/ingest", // when dealing with the self-hosted version of OpenReplay
__DISABLE_SECURE_MODE: true,
});
setTracker(tracker);
})();
}, []);
[...]
Контекст Tracker
Section titled Контекст Trackerэтот метод позволяет создать контекст, который, в свою очередь, упрощает управление состоянием трекера и вызов его различных API.
import { createContext } from "react"
import {v4 as uuidV4} from 'uuid'
import { useReducer } from "react"
export const TrackerContext = createContext()
function defaultGetUserId() {
return uuidV4()
}
async function newTracker(config) {
// we use dynamic import to make sure that tracker is started inside browser env
const { tracker } = await import("@openreplay/tracker");
const getUserId = (config?.userIdEnabled && config?.getUserId) ? config.getUserId : defaultGetUserId
let userId = null;
const trackerConfig = {
projectKey: config?.projectKey || process.env.NEXT_PUBLIC_OPENREPLAY_PROJECT_KEY
}
tracker.configure(trackerConfig);
if(config?.userIdEnabled) {
userId = getUserId()
tracker.setUserID(userId)
}
return tracker
}
function reducer(state, action) {
switch(action.type) {
case 'init': {
if(!state.tracker) {
console.log("Instantiaing the tracker for the first time...")
return {...state, tracker: newTracker(state.config)}
}
return state
}
case 'start': {
console.log("Starting tracker...")
state.tracker.start()
return state
}
}
}
export default function TrackerProvider({children, config = {}}) {
let [state, dispatch] = useReducer(reducer, {tracker: null, config})
let value = {
startTracking: () => dispatch({type: 'start'}),
initTracker: () => dispatch({type: 'init'})
}
return <TrackerContext.Provider value={value}>{children}</TrackerContext.Provider>
}
Этот провайдер предоставляет пользователю 2 метода:
initTracker: который создаёт экземпляр трекера с предоставленной конфигурацией.startTracking: который запускает процесс отслеживания.
Этот провайдер также принимает объект «конфигурации», который вы можете расширять для будущих возможностей. В этом примере показано, как при необходимости включить возможность однозначной идентификации пользователей. Вы можете использовать UUID по умолчанию, который будет уникальным для каждого пользователя при каждом посещении страницы. В качестве альтернативы вы можете предоставить пользовательскую функцию getUserId в составе конфигурации.
С помощью вашей пользовательской функции вы можете передавать идентификатор клиента вашего магазина, адрес электронной почты пользователя или что-либо ещё, что однозначно идентифицирует пользователя в вашем приложении. Таким образом вы сможете отслеживать повторы их сессий с течением времени на случай, если у них возникнет конкретная проблема, о которой не сообщают другие.
Обработка «projectKey» в вашем коде
Section titled Обработка «projectKey» в вашем кодеОбратите внимание, что настраиваемый вами projectKey — это тот, который предоставляется платформой OpenReplay. По соображениям безопасности это значение не следует хранить жёстко прописанным (hardcoded) в коде, а лучше держать его в каком-либо файле/системе конфигурации.
В этом примере я пользуюсь файлами .env от Next. Что вам нужно понять: если вы не добавите к переменной окружения префикс NEXT_PUBLIC, ваш клиентский код (трекер) не получит к ней доступ.
Если это для вас неприемлемо, вы можете использовать getStaticProps внутри первой страницы, которую посещают ваши пользователи, чтобы получить это значение до создания экземпляра трекера. Оба примера вы можете увидеть ниже.
Использование контекста трекера
Section titled Использование контекста трекераИмпортируйте и оберните ваше приложение в TrackerProvider, который мы создали ранее, вот так:
import '../styles/globals.css'
import TrackerProvider from '../context/trackerContext'
function MyApp({ Component, pageProps }) {
return <TrackerProvider>
<Component {...pageProps} />
</TrackerProvider>
}
export default MyApp
Это файл _app.js, который служит точкой входа для всего приложения.
А затем вы можете запускать отслеживание из любого компонента по вашему желанию, например так:
import { useContext, useEffect } from 'react'
import { TrackerContext } from '../context/trackerContext'
import styles from '../styles/Home.module.css'
export default function YourComponent({projectKey}) {
const {initTracker, startTracking} = useContext(TrackerContext)
useEffect( () => {
initTracker()
startTracking()
}, [])
//.... rest of your code
}
Если вам не нужен такой уровень контроля, вы можете объединить оба сообщения — «сообщение init» и «сообщение start tracking», — чтобы для запуска отслеживания достаточно было вызвать всего одну функцию.
Есть вопросы?
Section titled Есть вопросы?Чтобы посмотреть полный код работающего приложения на основе Next, вы можете заглянуть в этот репозиторий.
Если у вас возникнут какие-либо проблемы с настройкой трекера в вашем проекте на основе Next, свяжитесь с нами в нашем сообществе Slack и задайте вопросы нашим разработчикам напрямую!