# Vev Developer > Building no-code with code import Table from '../../components/Table'; ## Tracking and Analytics [Vev](https://vev.design) takes an agnostic approach to analytics and *does not* directly track visitors on Vev-created content or pages. However, we offer tools and methods to help you implement your preferred tracking solutions. This can be done through our [hosting integrations](https://www.vev.design/features/integrations/) or by using *event tracking* as described in this article. :::info [Vev's privacy policy](https://www.vev.design/legal/privacy-policy/): Vev does not have a direct relationship with Customers’ End Users. A “Customer End User” is an individual that provides their Personal Information to our Customers. We do not control the purposes nor the means by which this Personal Information is collected, and we are not in a direct relationship with Customer End Users. As described in. ::: ### Integration To implement event-based tracking, you need to listen for all Vev tracking events. This is done by listening for the `vev.track` event on the `window` object. Once captured, you can forward the event data to your preferred tracking tool, internal data repository, or any similar system. ```js window.addEventListener('vev.track', (e) => { const event = e.detail; console.log('event', event); }); ``` Example: Adobe Analytics Implementation ```js window.addEventListener('vev.track', (e) => { const event = e.detail.data; // Example: Send to Adobe Analytics alloy('sendEvent', { type: event.type, data: { ...event.data, vevProjectKey: event.metaData.projectKey, vevPageKey: event.metaData.pageKey, }, }); }); ``` #### Event data structure Vev offers two methods for creating tracking events: standard events and interaction-based event tracking. The `data` object is unique to each event type, while `metaData` remains consistent across all events.

Specific data for the event.

], [ { name: 'metaData', type: 'object' }, () => ( <> projectKey string
pageKey string
timestamp number
), ], ]} /> ### Standard events
( <> projectKey string
projectName string
breakpoint string ), ], [ { name: 'VEV_PAGE_LOAD', type: 'string' }, 'Dispatches when the page load', () => ( <> pageKey string
pageName string
projectKey string
breakpoint string ), ], [ { name: 'VEV_LINK_CLICK', type: 'string' }, 'Dispatches when an external link is clicked', () => ( <> url string
), ], [ { name: 'VEV_VIDEO_PLAY', type: 'string' }, 'Dispatches when an video is started', () => ( <> videoUrl string
totalPlayTime number (seconds)
percentagePlayed number (percentage) ), ], [ { name: 'VEV_VIDEO_STOP', type: 'string' }, 'Dispatches when an video is stopped or paused', () => ( <> videoUrl string
totalPlayTime number (seconds)
percentagePlayed number (percentage) ), ], [ { name: 'VEV_VIDEO_END', type: 'string' }, 'Dispatches when an video is fully played.', () => ( <> videoUrl string
totalPlayTime number (seconds)
percentagePlayed number (percentage) ), ], [ { name: 'VEV_VIDEO_PROGRESS', type: 'string' }, 'Dispatches the progress of a video in seconds.', () => ( <> videoUrl string
videoName string
progress number (seconds)
totalPlayTime number (seconds)
percentagePlayed number (percentage) ), ], ]} /> ### Custom events Custom events can be added using [interactions](https://help.vev.design/en/articles/8449049-how-to-use-interactions). For these events, the `type` and `data` are defined by the designer within the design editor. Custom events can be linked to various interaction triggers, such as `onVisible`, `onScroll`, and more. They are typically used for tracking call-to-action (CTA) interactions. ![interactionTracking](.//assets/interaction-tracking.png) ## Components ### Image The `Image` component can be used with the `type: image` schema field. #### Example ```jsx import React from 'react'; import { registerVevComponent, Image } from '@vev/react'; const MyComponent = (props) => ; registerVevComponent(MyComponent, { name: 'My component', props: [ { name: 'image', type: 'image', }, ], }); export default MyComponent; ``` #### Interface ```ts type Props = { className?: string; sizes?: [number, number][]; src?: string | { key: string }; style?: { [attr: string]: number | string }; }; ``` ### Link The `Link` component can be used together with the `type: link` schema field. ##### Example ```jsx import React from 'react'; import { registerVevComponent, Link } from '@vev/react'; const MyComponent = (props) => ; registerVevComponent(MyComponent, { name: 'My component', props: [ { name: 'link', type: 'link', }, ], }); export default MyComponent; ``` #### Interface ```ts type Props = { /** * Preset for what linkType the field should be. * 0: Page, 1: Element, 2: External link, 3: Email, 4: Phone. */ mode: 0 | 2 | 3 | 4; href?: string; page?: string; target?: boolean; phone?: string; email?: string; }; ``` ### Render The `Render` component is used to render a [Vev](https://www.vev.design/) project in your React application. The component supports [server side rendering](https://web.dev/rendering-on-the-web/) using [Suspense](https://react.dev/reference/react/Suspense), which means it will deliver static HTML on the server (if the app is built for server side rendering using Suspense) and hydrate on the client. This is also compatible with [NextJS](https://nextjs.org/) if you are using the [app routing feature](https://beta.nextjs.org/docs/app-directory-roadmap). :::caution To use this component with [NextJS](https://nextjs.org/) you have to [opt-in to the app directory routing](https://beta.nextjs.org/docs/installation). ::: This component will also work in a traditional React application, but the component will only render client side. ##### Example ```jsx import React from 'react'; import { Render as VevRender } from '@vev/react'; const MyComponent = (props) => { return ; }; export default MyComponent; ``` :::info To find the `projectKey` and `pageKey` look at your [Vev Editor](https://editor.vev.design) URL: ``` https://editor.vev.design/edit/[projectKey]/[pageKey] ``` ::: #### Interface ```ts type Props = { projectKey: string; pageKey: string; noCache: boolean; fallback: React.ReactNode; // Render a fallback component when loading }; ``` ## Hooks These hooks offer different way to interact with the Vev Editor. ### useIntersection Tracks the portion of an element that intersects with the visible area of the screen (the viewport). ```ts const el_intersection: false | IntersectionObserverEntry = useIntersection(ref: React.RefObject, options?: IObserverOptions); ``` ##### Interface ```ts interface IntersectionObserverEntry { /** * Properties of the tracked reference element */ boundingClientRect: DOMRectReadOnly; /** * Visible amount of the tracked reference element */ intersectionRatio: number; /** * Properties of only the visible portion of the tracked reference element (a subset of `boundingClientRect`) */ intersectionRect: DOMRectReadOnly; isIntersecting: boolean; rootBounds: DOMRectReadOnly | null; target: Element; time: number; } interface IObserverOptions { /** * Number of times the hook updates as the tracked element enters the visible screen. Defaults to 1. */ steps?: number; /** * Decimal values indicating the intersection percentage at which the hook updates. */ threshold?: number[]; } ``` It is not possible to define both a step and a threshold. Define one at most. ##### Example Display the percentage of a widget that intersects with the viewport. Update this value 10 times over the course of the widget’s entrance into the viewport. ```tsx import { useRef } from 'react'; import { useIntersection } from '@vev/react'; export default function () { const widgetReference = useRef(null); const intersection = useIntersection(widgetReference, { steps: 10 }); return (

{intersection.intersectionRatio * 100}

); } ``` ### useDevice Vev projects can be custom-designed for various presentation modes such as desktop, tablet, or mobile. `useDevice()` returns the currently active mode `('desktop' | 'tablet' | 'mobile')`. ##### Usage ```ts const device: string = useDevice(); ``` ##### Example ```tsx import { useDevice } from '@vev/react'; export default function () { const device: 'desktop' | 'tablet' | 'mobile' = useDevice(); return

Device: {device}

; } ``` ### useEditorState For better widget usability, consider changing the state of your widget depending on which mode the user is in. For example, play a video when in preview mode, but stop it when in editor mode. Or, if the user is changing the background color of a hidden dropdown in your widget, reveal that dropdown when its background colour property is being changed. `useEditorState()` returns the following: * `disabled: boolean` - true when in editor mode, false when in preview mode. * `rule: string` - tells which CSS rule the user is editing. Sets to ‘host’ when no rule is being edited . * `selected: boolean` - true when the widget is selected in editor mode. ##### Example ```tsx import { useEditorState } from '@vev/react'; import { useState, useEffect, useRef } from 'react'; export default function ({ url }: Props) { const { disabled } = useEditorState(); const videoReference = useRef(null); // this function runs on every value change of 'disabled' useEffect(() => { // If disabled, pause video if (disabled) { videoReference.current.pause(); } else { videoReference.current.play(); } }, [disabled]); return