openpanel icon indicating copy to clipboard operation
openpanel copied to clipboard

BUG: _window_op.call is not a function

Open ps173 opened this issue 1 month ago • 3 comments

I have set up openpanel on my next js as suggested in the documentation. I have added a extra useEffect to track the user visit on the page or route ( seems to be causing race condition with the sdk ). This is how things look on my end:

export default async function AppLayout({
  children,
}: {
  children: React.ReactNode;
}) {
// Ignore the business provider wrapper function. Basically a context wrapper with error boundary
  return (
    <BusinessProviderWrapper>
      <OpenPanelIdentifier />
      {children}
      <Toaster />
    </BusinessProviderWrapper>
  );
}

and below is the OpenPanelIdentifier

"use client";

import { useEffect, useRef } from "react";
import { useSession } from "@/lib/auth-client";
import { useOpenPanel } from "@openpanel/nextjs";

/**
 * OpenPanel User Identifier
 *
 * Automatically identifies users in OpenPanel analytics.
 */
export function OpenPanelIdentifier() {
  const op = useOpenPanel();
  const { data: session } = useSession();
  const hasIdentified = useRef(false);

  const extractFirstName = (fullName: unknown): string | undefined => {
    if (!fullName || typeof fullName !== "string") return undefined;
    const trimmed = fullName.trim();
    if (!trimmed) return undefined;
    const firstName = trimmed.split(/\s+/)[0];
    return firstName.length > 0 && firstName.length <= 50
      ? firstName
      : undefined;
  };


  useEffect(() => {
    if (!op || !session?.user || hasIdentified.current) {
      return;
    }

    const identifyUser = async () => {
      try {
        const user = session.user;
        if (!user.id || !user.email) return;

        const firstName = extractFirstName(user.name);

        const identifyPayload = {
          profileId: user.id,
          email: user.email,
          ...(firstName && { firstName }),
          properties: {
            signupDate:
              user.createdAt instanceof Date
                ? user.createdAt.toISOString()
                : new Date(user.createdAt || Date.now()).toISOString(),
          },
        };

        if (process.env.NODE_ENV !== "production") {
          console.log("[OpenPanel] Identifying user", {
            profileId: user.id,
            hasFirstName: !!firstName,
          });
        }

        op.identify(identifyPayload);
        hasIdentified.current = true;

      } catch (error) {
        console.error(
          "[OpenPanel] Identification failed",
          error instanceof Error ? error.message : String(error),
        );
      }
    };

    identifyUser();
  }, [op, session]);

  return null;
}

When I go to any page under the layout, I get following error in my browser console

15:13:59.717 Navigated to http://localhost:3000/big-doe/posts
15:13:59.720 Reloaded
15:14:07.913 [Client Instrumentation Hook] Slow execution detected: 72ms (Note: Code download overhead is not included in this measurement) [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.249 [Analytics] Scripts disabled in development [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.250 [Analytics] Scripts disabled in development [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.258 [GoogleMapsProvider] NEXT_PUBLIC_GOOGLE_MAPS_API_KEY is not set. Google Maps will not be available. [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.260 [GoogleMapsProvider] NEXT_PUBLIC_GOOGLE_MAPS_API_KEY is not set. Google Maps will not be available. [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.264 [Analytics] Client instance initialized [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.265 [Analytics] Environment: development [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.265 [Analytics] Tracking enabled: false [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.265 [Analytics] ⚠️  Tracking DISABLED in development environment [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.281 [Analytics] Server instance initialized [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.281 [Analytics] Environment: development [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.281 [Analytics] Tracking enabled: false [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.281 [Analytics] ⚠️  Tracking DISABLED in development environment [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.281 [Analytics] To test tracking locally, set ENABLE_ANALYTICS_IN_DEV=true [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.282 OpenPanel.dev - Initialized 
Object { clientId: "211c54e1-b706-4065-932c-3a9ca7682af6", clientSecret: undefined }
[console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.397 [Analytics] Skipping page view (disabled in development) [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:08.935 [Fast Refresh] rebuilding [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:09.899 [Fast Refresh] done in 1277ms [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:10.797 Image with src "https://img.logo.dev/codeword.tech?token=[REDACTED]&size=64" has either width or height modified, but not the other. If you use CSS to change the size of your image, also include the styles 'width: "auto"' or 'height: "auto"' to maintain the aspect ratio. [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:11.172 OpenPanel.dev - Initialized 
Object { apiUrl: "/api/op", clientId: "211c54e1-b706-4065-932c-3a9ca7682af6", trackScreenViews: true, trackOutgoingLinks: true, sdk: "nextjs", sdkVersion: "1.0.16" }
[console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:11.182 OpenPanel.dev - Track page view [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:12.789 [Fast Refresh] rebuilding [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:12.816 [Fast Refresh] done in 128ms [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:13.332 [OpenPanel] Identifying user 
Object { profileId: "2cDaoqnr0Exch3FeatTUlt3Ztj9kU7zp", hasFirstName: true, hasAttribution: false, attributionKeys: [] }
[console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:13.336
[OpenPanel] Identification failed _window_op.call is not a function [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
    instrumentConsole console.ts:39
    overrideMethod <anonymous code>:1
    error intercept-console-error.ts:44
    identifyUser openpanel-identifier.tsx:100
    useEffect openpanel-identifier.tsx:107
    react_stack_bottom_frame react-dom-client.development.js:23668
    runWithFiberInDEV react-dom-client.development.js:874
    commitHookEffectListMount react-dom-client.development.js:12344
    commitHookPassiveMountEffects react-dom-client.development.js:12465
    commitPassiveMountOnFiber react-dom-client.development.js:14386
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14389
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14389
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14389
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14389
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14389
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14389
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14389
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14389
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14389
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14379
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14513
    recursivelyTraversePassiveMountEffects react-dom-client.development.js:14359
    commitPassiveMountOnFiber react-dom-client.development.js:14398
    flushPassiveEffects react-dom-client.development.js:16337
    flushPendingEffects react-dom-client.development.js:16298
    flushSpawnedWork react-dom-client.development.js:16264
    commitRoot react-dom-client.development.js:15997
    commitRootWhenReady react-dom-client.development.js:15227
    performWorkOnRoot react-dom-client.development.js:15146
    performSyncWorkOnRoot react-dom-client.development.js:16830
    flushSyncWorkAcrossRoots_impl react-dom-client.development.js:16676
    processRootScheduleInMicrotask react-dom-client.development.js:16714
    scheduleImmediateRootScheduleTask react-dom-client.development.js:16849
    (Async: VoidFunction)
    scheduleImmediateRootScheduleTask react-dom-client.development.js:16843
    ensureRootIsScheduled react-dom-client.development.js:16637
    scheduleUpdateOnFiber react-dom-client.development.js:14978
    forceStoreRerender react-dom-client.development.js:7390
    subscribeToStore react-dom-client.development.js:7375
    emitChange index.mjs:18
    notify index.js:54
    set index.js:70
    onSuccess better-auth.BYWGbmZ5.mjs:27
    betterFetch fetch.ts:141
    $fetch index.ts:95
    fn better-auth.BYWGbmZ5.mjs:20
    timeoutId better-auth.BYWGbmZ5.mjs:84
    sentryWrapped helpers.ts:117
    (Async: setTimeout handler)
    _wrapTimeFunction browserapierrors.ts:115
    useAuthQuery better-auth.BYWGbmZ5.mjs:82
    listener index.js:119
    <anonymous> index.js:16
    <anonymous> index.js:16
    listen index.js:127
    get index.js:13
    useStore index.mjs:12
    <anonymous> index.mjs:47
    SentryUserIdentifier sentry-user-identifier.tsx:19
    react_stack_bottom_frame react-dom-client.development.js:23583
    renderWithHooks react-dom-client.development.js:6792
    updateFunctionComponent react-dom-client.development.js:9246
    beginWork react-dom-client.development.js:10806
    runWithFiberInDEV react-dom-client.development.js:874
    performUnitOfWork react-dom-client.development.js:15726
    workLoopConcurrentByScheduler react-dom-client.development.js:15720
    renderRootConcurrent react-dom-client.development.js:15695
    performWorkOnRoot react-dom-client.development.js:14989
    performWorkOnRootViaSchedulerTask react-dom-client.development.js:16815
    performWorkUntilDeadline scheduler.development.js:45
    (Async: EventHandlerNonNull)
    <anonymous> scheduler.development.js:223
    <anonymous> scheduler.development.js:364
    instantiateModule dev-base.ts:241
    runModuleExecutionHooks dev-base.ts:275
    instantiateModule dev-base.ts:235
    getOrInstantiateModuleFromParent dev-base.ts:162
    commonJsRequire runtime-utils.ts:366
    <anonymous> index.js:6
15:14:13.669 [Fast Refresh] rebuilding [console.ts:39:14](file:///Users/memmehsloth/Dev/spotbeam/node_modules/%40sentry/core/src/instrument/console.ts)
15:14:15.370 [Fast Refresh] done in 1806ms

version: "@openpanel/nextjs": "^1.0.16"

ps173 avatar Nov 21 '25 10:11 ps173

Can you try @openpanel/[email protected]?

lindesvard avatar Nov 22 '25 20:11 lindesvard

Hi @lindesvard, even after updating to @openpanel/[email protected] the error still persists

ps173 avatar Nov 26 '25 08:11 ps173

Can you try to clear your cache (hard refresh) and also bump the nextjs version again.

lindesvard avatar Nov 26 '25 08:11 lindesvard

Hi @lindesvard, the current nextjs version I am running is 15.5.4. Although I couldn't bump the version but I tried clearing the cache and yet the error persisted. Is this due to being on an older version of next ?

ps173 avatar Dec 01 '25 08:12 ps173

Is this live somewhere so I can test it?

lindesvard avatar Dec 02 '25 20:12 lindesvard

I am facing the same issue.

"@openpanel/nextjs": "^1.0.8", "next": "15.5.7", "react": "19.1.0", "react-dom": "19.1.0"

Error Type

Console TypeError

Error Message

_window_op.call is not a function

at SearchBar.useCallback[performSearch] (src/lib/layouts/main/search-bar.tsx:47:20)

Code Frame

45 | setSearchResults(response.data); 46 | // Track successful search

47 | op.track('search', { | ^ 48 | search_term: searchText, 49 | results_count: response.data.length, 50 | search_source: 'search_bar'

Next.js version: 15.5.7 (Turbopack)

Chirag-kalsariya avatar Dec 14 '25 17:12 Chirag-kalsariya

Can someone create a reproducible repo so I can try it out?

lindesvard avatar Dec 16 '25 14:12 lindesvard