> ## Documentation Index
> Fetch the complete documentation index at: https://developer.cashbackhive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# React (Vite, CRA, Remix)

> Install the Cashback Hive SDK in a React single-page app built with Vite, Create React App or Remix, and wait for readiness with a small custom hook.

For React apps without a framework script component, load the SDK from `index.html` and consume it with a hook.

**1. Add the script to index.html**

```html index.html theme={null}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>My app</title>
    <script
      src="https://sdk.cashbackhive.com/sdk.js"
      data-key="cbh_pk_your_publishable_key"
      async
    ></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
```

For Remix, put the tag in `app/root.tsx` inside `<head>` or `<body>`.

**2. Add type declarations**

Copy the declaration file from the [Types reference](https://developer.cashbackhive.com/reference/types.md#typescript-declarations) into `src/types/cashback-hive.d.ts`.

**3. Create a hook**

```ts src/hooks/useCashbackHive.ts theme={null}
import { useSyncExternalStore } from "react";
import type { CashbackHiveSdk } from "../types/cashback-hive";

function subscribe(onStoreChange: () => void) {
  window.addEventListener("cbh:ready", onStoreChange);
  return () => window.removeEventListener("cbh:ready", onStoreChange);
}

function getSnapshot(): CashbackHiveSdk | null {
  const sdk = window.CashbackHive;
  return sdk?.initialized ? sdk : null;
}

export function useCashbackHive(): CashbackHiveSdk | null {
  return useSyncExternalStore(subscribe, getSnapshot, () => null);
}
```

Using `useSyncExternalStore` (rather than `useEffect` + `useState`) handles the case where the SDK finished initialising before your component mounted.

**4. Use it**

```tsx src/App.tsx theme={null}
import { useCashbackHive } from "./hooks/useCashbackHive";

export default function App() {
  const sdk = useCashbackHive();

  if (!sdk) return <p>Loading…</p>;

  return (
    <button onClick={() => sdk.auth.signIn()}>
      Activate cashback
    </button>
  );
}
```

## Loading the script from JavaScript

If you can't edit `index.html` (for example in an embedded widget), inject the tag at runtime. Guard against loading it twice.

```ts theme={null}
export function loadCashbackHive(key: string) {
  if (document.querySelector('script[src="https://sdk.cashbackhive.com/sdk.js"]')) {
    return;
  }
  const script = document.createElement("script");
  script.src = "https://sdk.cashbackhive.com/sdk.js";
  script.async = true;
  script.dataset.key = key;
  document.head.appendChild(script);
}
```

> [!NOTE]
>
> `data-key` is read from `document.currentScript` when the SDK executes, so set `dataset.key` **before** appending the element to the DOM.

## Content Security Policy

See [Content Security Policy](https://developer.cashbackhive.com/guides/content-security-policy.md) if your app sets one.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.