React Integration Guide

Install IssueCapture in React

Add bug reporting to your React application in 5 minutes. Works with Create React App, Vite, and any React setup.

Quick Summary

  • Time: 2-5 minutes (7 simple steps)
  • Prerequisites: React 16.8+, Jira account, IssueCapture account (free)
  • Method: Script tag in index.html or programmatic useEffect
  • Works with: Create React App, Vite, React Router, Redux
  • Bundle size: 32KB initial (152KB for screenshot & annotation tools, lazy-loaded)

Prerequisites

  • React 16.8 or higher (hooks support)
  • Create React App, Vite, or any React bundler
  • Jira Cloud account (Software or JSM)
  • IssueCapture account (sign up free)

Step-by-Step Installation

1

Get Your API Key

Sign up for IssueCapture and retrieve your widget API key from the dashboard

  • Go to https://issuecapture.com/signup and create a free account
  • Connect your Jira instance via OAuth
  • Navigate to the Widgets page and create a new widget
  • Copy your API key (starts with "ic_")
2

Add Environment Variable

Store your API key in your environment configuration

  • Create React App: Use REACT_APP_ prefix
  • Vite: Use VITE_ prefix
  • Never commit .env files to version control
  • Restart dev server after adding environment variables
# .env (Create React App)
REACT_APP_ISSUECAPTURE_API_KEY=ic_your_api_key_here

# .env.local (Vite)
VITE_ISSUECAPTURE_API_KEY=ic_your_api_key_here
3

Install via Script Tag (Recommended)

Add IssueCapture to your public/index.html file

  • Place script tag at the end of <body> for optimal loading
  • Create React App automatically replaces %REACT_APP_*% tokens
  • Vite requires manual replacement (see Step 4 for programmatic approach)
  • type="module" is required for ESM imports
<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Your React App</title>
  </head>
  <body>
    <div id="root"></div>

    <!-- IssueCapture Widget -->
    <script type="module">
      import IssueCapture from 'https://issuecapture.com/widget.js';

      IssueCapture.init({
        apiKey: '%REACT_APP_ISSUECAPTURE_API_KEY%', // CRA
        // apiKey: '%VITE_ISSUECAPTURE_API_KEY%',   // Vite
        trigger: 'auto',
        button: {
          position: 'bottom-right',
          text: 'Report Bug'
        }
      });
    </script>
  </body>
</html>
4

Alternative: Programmatic Initialization

Initialize IssueCapture from your React component using useEffect

  • Loads widget only when component mounts
  • Works with both Create React App and Vite
  • Cleanup function destroys widget on unmount
  • Useful for single-page applications with routing
// src/App.jsx or src/App.tsx
import { useEffect } from 'react';

function App() {
  useEffect(() => {
    // Dynamically load IssueCapture widget
    const script = document.createElement('script');
    script.type = 'module';
    script.innerHTML = `
      import IssueCapture from 'https://issuecapture.com/widget.js';

      IssueCapture.init({
        apiKey: '${process.env.REACT_APP_ISSUECAPTURE_API_KEY || process.env.VITE_ISSUECAPTURE_API_KEY}',
        trigger: 'auto',
        button: {
          position: 'bottom-right',
          text: 'Report Bug'
        }
      });
    `;
    document.body.appendChild(script);

    return () => {
      // Cleanup on unmount
      if (window.IssueCapture) {
        window.IssueCapture.destroy();
      }
    };
  }, []);

  return (
    <div className="App">
      <h1>Your React Application</h1>
      {/* Your components */}
    </div>
  );
}

export default App;
5

Custom Trigger Component

Create a React component to trigger the widget

  • Use window.IssueCapture.open() to open programmatically
  • Check if IssueCapture exists before calling
  • Add aria-label for accessibility
  • Integrate into navbar, footer, or error boundaries
// src/components/BugReportButton.jsx
import React from 'react';

export default function BugReportButton() {
  const openWidget = () => {
    if (window.IssueCapture) {
      window.IssueCapture.open();
    }
  };

  return (
    <button
      onClick={openWidget}
      className="bug-report-btn"
      aria-label="Report a bug"
    >
      Report Bug
    </button>
  );
}

// Usage in your app:
// import BugReportButton from './components/BugReportButton';
// <BugReportButton />
6

Set User Context (Optional)

Pre-fill user information for authenticated users

  • Pre-fill reporter name and email for authenticated users
  • Update user context when auth state changes
  • Component field maps to Jira components for routing
  • Improves bug report context for developers
// src/App.jsx
import { useEffect } from 'react';
import { useAuth } from './hooks/useAuth'; // Your auth hook

function App() {
  const { user } = useAuth();

  useEffect(() => {
    if (window.IssueCapture && user) {
      // Update user context when user logs in
      window.IssueCapture.init({
        apiKey: process.env.REACT_APP_ISSUECAPTURE_API_KEY,
        trigger: 'auto',
        user: {
          name: user.name,
          email: user.email,
          component: 'Frontend' // Optional: Jira component
        }
      });
    }
  }, [user]);

  return <div className="App">{/* Your app */}</div>;
}
7

Test the Integration

Verify IssueCapture is working correctly

  • Start your dev server: npm start or npm run dev
  • Open your app in the browser
  • You should see the floating bug report button
  • Click it and submit a test issue
  • Check your Jira project for the created issue
  • Open browser console and type: window.IssueCapture.isOpen()

Troubleshooting

TypeScript: Property 'IssueCapture' does not exist on type 'Window'

Add type declarations to your project:

// src/types/issuecapture.d.ts
interface IssueCaptureAPI {
  init(config: {
    apiKey: string
    trigger?: string | 'auto'
    button?: {
      position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
      text?: string
      icon?: string
    }
    user?: {
      name?: string
      email?: string
      component?: string
    }
  }): void
  open(): void
  close(): void
  isOpen(): boolean
  destroy(): void
}

declare global {
  interface Window {
    IssueCapture?: IssueCaptureAPI
  }
}

export {}

Environment variables not working

  • Create React App: Must use REACT_APP_ prefix
  • Vite: Must use VITE_ prefix
  • Restart dev server after adding/changing .env
  • Never use NEXT_PUBLIC_ prefix in React (Next.js only)

Widget loads multiple times (React Router)

If using React Router, initialize widget once in root component:

// src/App.jsx - Initialize once at root level
useEffect(() => {
  // Initialize IssueCapture only once
  if (!window.IssueCapture) {
    // Load script...
  }
}, []); // Empty dependency array = run once

CORS errors when submitting issues

  • Add localhost:3000 to allowed domains in dashboard
  • Add production domain to allowed domains
  • Check IssueCapture dashboard → Widgets → Domains

Advanced Configuration

Event Listeners

IssueCapture.init({
  apiKey: process.env.REACT_APP_ISSUECAPTURE_API_KEY,
  trigger: 'auto',
  onOpen: () => {
    console.log('Widget opened')
  },
  onClose: () => {
    console.log('Widget closed')
  },
  onSubmit: (data) => {
    console.log('Issue submitted:', data)
    // Show success toast, etc.
  }
})

Error Boundary Integration

Automatically open IssueCapture when errors occur:

class ErrorBoundary extends React.Component {
  componentDidCatch(error, errorInfo) {
    // Log to IssueCapture
    if (window.IssueCapture) {
      window.IssueCapture.open()
    }
  }

  render() {
    return this.props.children
  }
}

Production Best Practices

  • Load widget asynchronously to avoid blocking
  • Use environment variables for API keys
  • Whitelist production domains in dashboard
  • Test on staging before deploying

Ready to get started?

Sign up for a free account and start collecting bug reports in your React app in minutes.