Gå til indhold

React Native

SDK’et leveres med et dedikeret React Native entry point@magicfeedback/popup-sdk/react-native — som klarer hele integrationen for dig: persistent storage, device info, platform, app-livscyklus, fejlopsamling og rendering af surveys i en Modal + WebView.

I de fleste apps er integrationen én komponent: pak din app ind i <DeepdotsProvider>.

Terminal window
npm install @magicfeedback/popup-sdk react-native-webview

To valgfrie pakker låser resten af funktionaliteten op. Installér begge, medmindre du har en grund til ikke at gøre det:

Terminal window
npm install react-native-mmkv react-native-device-info
Terminal window
cd ios && pod install
PakkePåkrævetHvad den giver dig
react-native-webviewRenderer survey-UI’et
react-native-mmkvAnbefaletBevarer user_id på tværs af app-genstarter (tilbagevendende brugere)
react-native-device-infoAnbefaletEnhedstype, OS-version, model, app-version (Technology-metrikker)

Alle er erklæret som valgfrie peer dependencies: SDK’et registrerer ved runtime, hvad der er installeret, og degraderer elegant. Uden MMKV lever user_id kun i hukommelsen, og der genereres et nyt ved hver opstart; uden react-native-device-info udelades enhedskonteksten.

App.tsx
import { DeepdotsProvider } from '@magicfeedback/popup-sdk/react-native';
export default function App() {
return (
<DeepdotsProvider
config={{
apiKey: 'YOUR_PUBLIC_API_KEY',
nodeEnv: __DEV__ ? 'development' : 'production',
userId: 'customer-123',
appVersion: '1.4.0',
// Udelad `analytics` for at forblive i dry-run-tilstand (events logges, intet sendes).
analytics: {
publicKey: 'YOUR_ANALYTICS_PUBLIC_KEY',
integration: 'YOUR_INTEGRATION_ID',
},
}}
>
<YourNavigation />
</DeepdotsProvider>
);
}

config tager samme objekt som init(config) — Provideren udfylder de React Native-specifikke felter (storage, device, platform) for dig.

OmrådeHvordan
Persistent identitetMMKV-instans (id: 'deepdots-sdk') når react-native-mmkv er installeret
Device inforeact-native-device-info når den er installeret
PlatformPlatform.OS'ios' / 'android' i analytics-konteksten
Engagement-tidAppStateonForeground() / onBackground() (flusher ved baggrund)
Fejlopsamlingglobal.ErrorUtils → uhåndterede JS-fejl som deepdots_app_crash
Survey-renderingReactNativePopupRenderer + en Modal med en WebView, monteret efter behov

To ting er ikke automatiske og kræver et par linjer fra dig: navigations-tracking og at starte triggerne.

useDeepdots() returnerer den delte DeepdotsPopups-instans hvor som helst under Provideren. Hele analytics-API’et er tilgængeligt — se Analytics-guiden.

import { useDeepdots } from '@magicfeedback/popup-sdk/react-native';
function ProductScreen() {
const dd = useDeepdots();
return (
<Button
title="Læg i kurv"
onPress={() => {
dd.track('add_to_cart', { product_id: 'p-123', value: 49.9 });
dd.triggerEvent('added_to_cart');
}}
/>
);
}

Provideren initialiserer SDK’et og henter popup-definitionerne, men den starter ikke triggerne — kald autoLaunch() én gang fra en komponent inde i Provideren:

function DeepdotsBootstrap() {
const dd = useDeepdots();
useEffect(() => {
dd.autoLaunch();
}, [dd]);
return null;
}

Alternativt kan du springe autoLaunch() over og vise popups imperativt med dd.triggerEvent('some_event') — matchende event-triggere udløses med det samme.

En popup begrænset til bestemte sprog (segments.lang) evalueres mod det sprog, SDK’et bestemte ved init(): dit eksplicitte language, ellers navigator.language, ellers Intl-lokalet. Netop den sidste fallback er det, der får det til at virke under Hermes, hvor navigator.language ikke findes. Der matches på præfiks, så et segment på en matcher en-US.

Vil du styre målretningen eksplicit i stedet for at stole på registreringen — anbefalet, når din app har sin egen i18n — så send sproget med i konfigurationen:

<DeepdotsProvider config={{ apiKey: 'YOUR_PUBLIC_API_KEY', language: 'es-ES' }}>

Når en popup vises, monterer Provideren en fuldskærms-Modal med en WebView med surveyen. Survey-HTML’en er selvstændig, men indlæser @magicfeedback/native fra et CDN, så rendering af en survey kræver netværksadgang. Popup-status (SHOWED / PARTIAL / COMPLETED) rapporteres automatisk til POST /sdk/popups, og det persistente user_id, session_id og den aktive mini_service injiceres i surveyens identitets-metadata.

React Native har ingen History API, så skærmvisninger registreres ikke automatisk. Rapportér dem med setScreen(name) — SDK’et udsender et deepdots_page_view-event med varigheden af den forrige skærm, når du rapporterer den næste.

Med React Navigation:

import { NavigationContainer, createNavigationContainerRef } from '@react-navigation/native';
import { useDeepdots } from '@magicfeedback/popup-sdk/react-native';
const navRef = createNavigationContainerRef();
function Navigation() {
const dd = useDeepdots();
const report = () => {
const route = navRef.getCurrentRoute();
if (route) dd.setScreen(route.name);
};
return (
<NavigationContainer ref={navRef} onReady={report} onStateChange={report}>
<YourStack />
</NavigationContainer>
);
}

Skærmnavne normaliseres på samme måde som web-stier: query strings fjernes, og numeriske/UUID-segmenter kollapser til :id, så /product/123 og /product/456 begge rapporteres som /product/:id.

Avanceret: manuel opsætning uden Provideren

Sektion kaldt “Avanceret: manuel opsætning uden Provideren”

Har du brug for din egen overflade (et bottom sheet, en dedikeret skærm) eller dit eget React-træ, så brug setupReactNative() og ReactNativePopupRenderer direkte. Begge kommer fra hoved-entry pointet.

import { useEffect, useRef, useState } from 'react';
import { AppState, Modal, Platform, View } from 'react-native';
import { WebView } from 'react-native-webview';
import { MMKV } from 'react-native-mmkv';
import DeviceInfo from 'react-native-device-info';
import {
DeepdotsPopups,
ReactNativePopupRenderer,
setupReactNative,
type ReactNativeSurveyPayload,
} from '@magicfeedback/popup-sdk';
const sdk = new DeepdotsPopups();
export function DeepdotsHost({ children }: { children: React.ReactNode }) {
const [survey, setSurvey] = useState<ReactNativeSurveyPayload | null>(null);
const rendererRef = useRef<ReactNativePopupRenderer | null>(null);
useEffect(() => {
const renderer = new ReactNativePopupRenderer({
onShow: (payload) => setSurvey(payload),
onHide: () => setSurvey(null),
});
rendererRef.current = renderer;
// Sætter rendereren, injicerer storage/device/platform, kalder init()
// og tilslutter AppState → onForeground/onBackground. Returnerer en oprydningsfunktion.
return setupReactNative(
sdk,
{ apiKey: 'YOUR_PUBLIC_API_KEY', nodeEnv: __DEV__ ? 'development' : 'production' },
{
mmkv: new MMKV({ id: 'deepdots-sdk' }),
deviceInfo: DeviceInfo,
appState: AppState,
platform: Platform.OS === 'ios' ? 'ios' : 'android',
renderer,
},
);
}, []);
return (
<>
{children}
{survey ? (
<Modal visible transparent animationType="slide">
<View style={{ flex: 1 }}>
<WebView
style={{ flex: 1 }}
originWhitelist={['*']}
javaScriptEnabled
source={{ html: survey.html, baseUrl: 'https://sdk.deepdots.com/' }}
onMessage={(e) => rendererRef.current?.handleMessage(e.nativeEvent.data)}
/>
</View>
</Modal>
) : null}
</>
);
}

Rendereren er en bro, ikke en stub: onShow giver dig { surveyId, productId, html } klar til <WebView source={{ html }}>, og handleMessage oversætter WebView-beskeder til SDK-events — første interaktion → popup_clicked (PARTIAL), fuldførelse → survey_completed (COMPLETED).

Render surveyen uden SDK’ets kort (renderChrome)

Sektion kaldt “Render surveyen uden SDK’ets kort (renderChrome)”

Fra 1.4.0: når du monterer din egen dekorerede container (en Modal, en bottom sheet eller en skærm med sit eget kort, baggrund, afrundede hjørner eller backdrop), send renderChrome: false i konfigurationen:

setupReactNative(
sdk,
{ apiKey: 'YOUR_PUBLIC_API_KEY', renderChrome: false },
{ /* deps */ },
);

Fra 1.3.0 tegner survey-HTML’en sit eget kort og backdrop (header med en lukkeknap, footer med navigationsknapperne, afrundet kort, nedtonet baggrund). Hvis din egen container også er dekoreret, stables de to til et “dobbelt modal” — et kort inde i et kort. renderChrome: false gør WebView-HTML’en gennemsigtig og kant-til-kant, så den fylder din container, mens surveyen forbliver fuldt funktionel (beskedbro, formular, back/start/complete/send-knapper og lukkeknappen). Du ejer den ydre ramme; SDK’et ejer surveyen.

Flaget påvirker kun React Native (survey-WebView-HTML’en). Det har ingen effekt på web-DOM-popuppen, og standard-<DeepdotsProvider> ignorerer det, fordi dens Modal allerede er gennemsigtig og fuldskærm (så den indbyggede sti viser ét enkelt kort). Brug det på den manuelle sti ovenfor.

renderChrome afgør, hvem der tegner rammen. Vil du omstyle det, der er indeni — formuleringer, svarmuligheder, vurderingsskalaer samt SDK’ets egen header, fremdriftslinje og footer — så send dit eget stylesheet i surveyCss. Det indsættes som det sidste stylesheet i WebView’en, så det vinder i kaskaden uden at røre de standardværdier, alle Deepdots-kunder deler.

Den side viser også de klassenavne, du kan målrette. Fra 1.5.0 eksponerer SDK’et de samme kroge i både web-popuppen og denne WebView, så ét stylesheet dækker begge platforme.

DepTypeStandard når den udelades
mmkvMMKV-instansconfig.storage, ellers in-memory
deviceInforeact-native-device-info-modulconfig.device, ellers udeladt
appStateAppStateIngen livscyklus-tilslutning
platform'ios' / 'android' / 'web'config.platform, ellers 'web'
rendererPopupRendererSDK’ets standard-renderer
errorUtilsglobal.ErrorUtilsglobalThis.ErrorUtils hvis den findes

Alle deps er valgfrie. Lavniveau-hjælpere eksporteres også, hvis du selv vil bygge delene: mmkvStorage(mmkv) (en synkron KeyValueStorage-adapter), collectRnDevice(deviceInfo) og buildSurveyHtml(options).