ReactionSaaS
Documentation

React installation

ReactifySDK · React

Custom elements work in JSX, but the script must run in the browser once. Use a tiny client component to inject the bundle; keep thread markup in the same subtree so layout is predictable.

In-page recorder vs hosted record page

WordPress shows a popup for "React To This" / "Stitch this" because the plugin sets window.reactifyWprtEmbed.apiKey before reactify.js runs. A script-only React install without that bootstrap turns those CTAs into links to https://api.reactionsaas.com/reactify/record. Set apiKey (and base) the same way below to get the WordPress-style modal.

1. Client-only script loader (with apiKey)

Bootstrap before appending the script. Use your publishable Reactify API key from the dashboard (same key the WordPress plugin stores).

ReactifyLoader.tsx
// ReactifyLoader.tsx — mark "use client"
import { useEffect } from "react";

const SRC = "https://reactify-cdn.s3.us-east-2.amazonaws.com/reactify.js?v=1.1.34";
const APP_BASE = "https://api.reactionsaas.com";

declare global {
  interface Window {
    reactifyWprtEmbed?: { base: string; apiKey: string };
    reactifyShopifyEmbed?: { base: string; apiKey: string };
    REACTIFY_EMBED_BASE?: string;
  }
}

/** Same gate WordPress/Shopify use: apiKey → in-page recorder; no key → opens https://api.reactionsaas.com/reactify/record. */
function bootstrapReactifyEmbed(apiKey: string) {
  const cfg = { base: APP_BASE.replace(/\/+$/, ""), apiKey: apiKey.trim() };
  window.reactifyWprtEmbed = cfg;
  window.reactifyShopifyEmbed = cfg;
  window.REACTIFY_EMBED_BASE = cfg.base;
}

export function ReactifyLoader({ apiKey }: { apiKey: string }) {
  useEffect(() => {
    if (typeof window === "undefined") return;
    bootstrapReactifyEmbed(apiKey);
    if (document.querySelector(`script[src="${SRC}"]`)) return;
    const s = document.createElement("script");
    s.src = SRC;
    s.async = true;
    document.body.appendChild(s);
  }, [apiKey]);
  return null;
}

2. Use the element

Prefer a concrete thread id for beat/stitch popups. Template-only shells may still deep-link to the hosted record page. TypeScript may warn on unknown intrinsic elements—add a reactify-thread declaration in a *.d.ts or suppress per line as below.

Component
import { ReactifyLoader } from "./ReactifyLoader";

export function ThreadSection() {
  const apiKey = process.env.REACT_APP_REACTIFY_API_KEY ?? ""; // or VITE_REACTIFY_API_KEY
  return (
    <>
      <ReactifyLoader apiKey={apiKey} />
      {/* eslint-disable-next-line react/no-unknown-property */}
      <reactify-thread
        thread="YOUR_THREAD_ID"
        data-base="https://api.reactionsaas.com"
      />
    </>
  );
}

Strict mode & Fast Refresh

Guard script injection with a DOM query (shown above) so double mount in development does not insert two tags. Thread state lives in the custom element; remounting the React tree recreates the element and refetches—pin keys if you need stability across navigations.