narkq / react-yandex-metrika

React component for Yandex.Metrika
128 stars 25 forks source link

Need example how to use it with NextJS router #47

Open dimuska139 opened 4 years ago

dimuska139 commented 4 years ago

Please give the example how to integrate this library with NextJS routing.

vvmspace commented 4 years ago

+1 Add examples of using with NextJS

dimuska139 commented 4 years ago

@vvmspace my current realization:

_app.tsx (custom _app.tsx)

import Router from 'next/router';
import {YMInitializer} from "react-yandex-metrika";
...
Router.events.on('routeChangeComplete', (url: string) => {
    // To hit only in production and only on client side (in browser)
    if (typeof window !== 'undefined' && process.env.NODE_ENV === 'production') {
        ym('hit', url);
    }
});

class MyApp extends App {
    componentDidMount() {
        // To hit only in production and only on client side (in browser)
        if (typeof window !== 'undefined' && process.env.NODE_ENV === 'production') {
            const url = window.location.pathname + window.location.search;
            ym('hit', url);
        }
        ...
   }
   ...
   render () {
        // @ts-ignore
        const {Component, pageProps, reduxStore, layoutProps} = this.props;
        return (
            <>
                {process.env.NODE_ENV === 'production' &&
                <YMInitializer
                    accounts={[parseInt(process.env.YM_COUNTER_ID as string)]}
                    options={{webvisor: true, defer: true}}
                    version="2"
                />
                }
                <Provider store={reduxStore}>
                    <ThemeProvider theme={theme}>
                        <CssBaseline />
                        <Layout {...layoutProps}>
                            <Component {...pageProps} />
                        </Layout>
                    </ThemeProvider>
                </Provider>
            </>
        )
    }
}
iksent commented 2 years ago

2021 hooks solution

1) Create new React component WithYandexMetrika.tsx:

import React, { ReactNode, useCallback, useEffect } from 'react'
import Router from 'next/router'
import ym, { YMInitializer } from 'react-yandex-metrika'

export type WithYandexMetrikaProps = {
  children: ReactNode
}

const enabled =
  process.env.NODE_ENV === 'production' &&
  process.env.YANDEX_METRIKA_ID

const WithYandexMetrika = (props: WithYandexMetrikaProps) => {
  const { children } = props

  const hit = useCallback((url) => {
    if (enabled) {
      ym('hit', url)
    } else {
      console.log(`%c[YandexMetrika](HIT)`, `color: orange`, url)
    }
  }, [])

  useEffect(() => {
    hit(window.location.pathname + window.location.search)
    Router.events.on('routeChangeComplete', (url: string) => hit(url))
  }, [])

  return (
    <>
      {enabled && (
        <YMInitializer
          accounts={[Number(process.env.YANDEX_METRIKA_ID)]}
          options={{ webvisor: true, defer: true }}
          version="2"
        />
      )}
      {children}
    </>
  )
}

export default WithYandexMetrika

2) _app.tsx: Just wrap your layout with <WithYandexMetrika> like with other providers 3) Set process.env.YANDEX_METRIKA_ID environment variable to your ID 4) Don't forget to pass env vars to client

olegyablokov commented 7 months ago

I have an e-commerce website that needs to have SSR for SEO purposes. useEffect in the root layout won't work because it is for client components. Anyone knows what can be done here?