Integrations
React Integration
Integrate Ask0 into your React app using our official React component. Easy setup with full TypeScript support and customizable UI.
Integrate Ask0 AI assistant into your React application to provide instant support and guidance to users.
Installation
Using Script Tag
The simplest way to add Ask0 to React:
// In your index.html or public/index.html
<script
src="https://assets.ask0.ai/scripts/ask.js"
data-project-id="YOUR_PROJECT_ID"
></script>Using React Component
For better control, create a React component:
npm install @ask0/react
yarn add @ask0/reactBasic Integration
Functional Component
import { useEffect } from 'react';
function App() {
useEffect(() => {
// Load Ask0 script
const script = document.createElement('script');
script.src = 'https://assets.ask0.ai/scripts/ask.js';
script.async = true;
script.dataset.projectId = process.env.REACT_APP_ASK0_PROJECT_ID;
document.body.appendChild(script);
return () => {
// Cleanup on unmount
if (document.body.contains(script)) {
document.body.removeChild(script);
}
if (window.ask0) {
window.ask0.destroy?.();
}
};
}, []);
return (
<div className="App">
{/* Your app content */}
</div>
);
}
export default App;Custom Hook
Create a reusable hook:
// hooks/useAsk0.js
import { useEffect, useCallback } from 'react';
export function useAsk0(config = {}) {
const {
projectId = process.env.REACT_APP_ASK0_PROJECT_ID,
position = 'bottom-right',
theme = 'auto',
} = config;
useEffect(() => {
if (!projectId) {
console.warn('Ask0: Project ID not provided');
return;
}
const script = document.createElement('script');
script.src = 'https://assets.ask0.ai/scripts/ask.js';
script.async = true;
script.dataset.projectId = projectId;
script.dataset.position = position;
script.dataset.theme = theme;
document.body.appendChild(script);
return () => {
if (document.body.contains(script)) {
document.body.removeChild(script);
}
};
}, [projectId, position, theme]);
const open = useCallback(() => {
window.ask0?.open();
}, []);
const close = useCallback(() => {
window.ask0?.close();
}, []);
const toggle = useCallback(() => {
window.ask0?.toggle();
}, []);
return { open, close, toggle };
}
// Usage in component
function MyComponent() {
const { open, close, toggle } = useAsk0();
return (
<button onClick={open}>
Open Support Chat
</button>
);
}Advanced Integration
Context Provider
Create a context for Ask0:
// context/Ask0Context.js
import React, { createContext, useContext, useEffect, useState } from 'react';
const Ask0Context = createContext(null);
export function Ask0Provider({ children, config }) {
const [isReady, setIsReady] = useState(false);
const [ask0, setAsk0] = useState(null);
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://assets.ask0.ai/scripts/ask.js';
script.async = true;
Object.entries(config).forEach(([key, value]) => {
script.dataset[key] = value;
});
script.onload = () => {
setAsk0(window.ask0);
setIsReady(true);
};
document.body.appendChild(script);
return () => {
if (document.body.contains(script)) {
document.body.removeChild(script);
}
};
}, [config]);
return (
<Ask0Context.Provider value={{ ask0, isReady }}>
{children}
</Ask0Context.Provider>
);
}
export function useAsk0Context() {
const context = useContext(Ask0Context);
if (!context) {
throw new Error('useAsk0Context must be used within Ask0Provider');
}
return context;
}
// Usage
function App() {
return (
<Ask0Provider config={{ projectId: 'YOUR_PROJECT_ID' }}>
<YourApp />
</Ask0Provider>
);
}
function SupportButton() {
const { ask0, isReady } = useAsk0Context();
return (
<button
onClick={() => ask0?.open()}
disabled={!isReady}
>
Get Help
</button>
);
}User Identification
Identify logged-in users:
import { useEffect } from 'react';
import { useAuth } from './hooks/useAuth'; // Your auth hook
function App() {
const { user } = useAuth();
useEffect(() => {
if (user && window.ask0) {
window.ask0.identify({
id: user.id,
email: user.email,
name: user.name,
plan: user.subscription?.plan,
signupDate: user.createdAt,
});
}
}, [user]);
return <div>Your App</div>;
}React Router Integration
Integrate with React Router:
import { useLocation } from 'react-router-dom';
import { useEffect } from 'react';
function Ask0RouterIntegration() {
const location = useLocation();
useEffect(() => {
if (window.ask0) {
// Track page views
window.ask0.trackPage(location.pathname);
// Page-specific configuration
if (location.pathname === '/pricing') {
window.ask0.setContext({
page: 'pricing',
showPricingHelp: true,
});
}
}
}, [location]);
return null;
}
// In your App component
function App() {
return (
<Router>
<Ask0RouterIntegration />
<Routes>
{/* Your routes */}
</Routes>
</Router>
);
}State Management
With Redux
// redux/ask0Slice.js
import { createSlice } from '@reduxjs/toolkit';
const ask0Slice = createSlice({
name: 'ask0',
initialState: {
isOpen: false,
isReady: false,
},
reducers: {
setReady: (state, action) => {
state.isReady = action.payload;
},
setOpen: (state, action) => {
state.isOpen = action.payload;
},
},
});
export const { setReady, setOpen } = ask0Slice.actions;
export default ask0Slice.reducer;
// Component
import { useDispatch, useSelector } from 'react-redux';
import { setOpen } from './redux/ask0Slice';
function SupportButton() {
const dispatch = useDispatch();
const isReady = useSelector(state => state.ask0.isReady);
const handleClick = () => {
window.ask0?.open();
dispatch(setOpen(true));
};
return (
<button onClick={handleClick} disabled={!isReady}>
Support
</button>
);
}With Context API
// context/AppContext.js
import { createContext, useContext, useState } from 'react';
const AppContext = createContext();
export function AppProvider({ children }) {
const [supportOpen, setSupportOpen] = useState(false);
const openSupport = () => {
window.ask0?.open();
setSupportOpen(true);
};
const closeSupport = () => {
window.ask0?.close();
setSupportOpen(false);
};
return (
<AppContext.Provider value={{ supportOpen, openSupport, closeSupport }}>
{children}
</AppContext.Provider>
);
}TypeScript Support
Add type definitions:
// types/ask0.d.ts
interface Ask0Config {
projectId: string;
position?: 'bottom-right' | 'bottom-left' | 'center';
theme?: 'light' | 'dark' | 'auto';
}
interface Ask0User {
id: string;
email?: string;
name?: string;
[key: string]: any;
}
interface Ask0Widget {
open: () => void;
close: () => void;
toggle: () => void;
identify: (user: Ask0User) => void;
setTheme: (theme: 'light' | 'dark') => void;
on: (event: string, callback: Function) => void;
destroy?: () => void;
}
declare global {
interface Window {
ask0?: Ask0Widget;
}
}
export {};
// Usage in component
import { FC } from 'react';
const SupportButton: FC = () => {
const handleClick = (): void => {
window.ask0?.open();
};
return <button onClick={handleClick}>Support</button>;
};Styling Integration
With Styled Components
import styled from 'styled-components';
const SupportButton = styled.button`
position: fixed;
bottom: 2rem;
right: 2rem;
padding: 0.75rem 1.5rem;
background: ${props => props.theme.primary};
color: white;
border-radius: 9999px;
border: none;
cursor: pointer;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: all 0.3s;
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
}
`;
function CustomTrigger() {
return (
<SupportButton onClick={() => window.ask0?.open()}>
Need Help?
</SupportButton>
);
}With Tailwind CSS
function TailwindTrigger() {
return (
<button
onClick={() => window.ask0?.open()}
className="fixed bottom-8 right-8 px-6 py-3 bg-blue-600 text-white
rounded-full shadow-lg hover:shadow-xl hover:-translate-y-0.5
transition-all duration-300"
>
Get Help
</button>
);
}Environment Configuration
REACT_APP_ASK0_PROJECT_ID=your_project_id
REACT_APP_ASK0_POSITION=bottom-right
REACT_APP_ASK0_THEME=auto// config/ask0.js
export const ask0Config = {
projectId: process.env.REACT_APP_ASK0_PROJECT_ID,
position: process.env.REACT_APP_ASK0_POSITION || 'bottom-right',
theme: process.env.REACT_APP_ASK0_THEME || 'auto',
};Testing
Jest Testing
// __tests__/Ask0.test.js
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import App from './App';
describe('Ask0 Integration', () => {
beforeEach(() => {
// Mock window.ask0
window.ask0 = {
open: jest.fn(),
close: jest.fn(),
toggle: jest.fn(),
};
});
it('should open Ask0 when button clicked', async () => {
render(<App />);
const button = screen.getByText('Get Help');
await userEvent.click(button);
expect(window.ask0.open).toHaveBeenCalled();
});
});Performance Optimization
Lazy Loading
import { lazy, Suspense } from 'react';
const Ask0Widget = lazy(() => import('./components/Ask0Widget'));
function App() {
return (
<div>
{/* Your app content */}
<Suspense fallback={null}>
<Ask0Widget />
</Suspense>
</div>
);
}Code Splitting
import { useEffect, useState } from 'react';
function App() {
const [loadAsk0, setLoadAsk0] = useState(false);
useEffect(() => {
// Load Ask0 after initial render
const timer = setTimeout(() => setLoadAsk0(true), 2000);
return () => clearTimeout(timer);
}, []);
return (
<div>
{/* App content */}
{loadAsk0 && <Ask0Integration />}
</div>
);
}Best Practices
React Integration Tips:
- Load Ask0 after initial render for better performance
- Use cleanup in useEffect to prevent memory leaks
- Identify users when they log in
- Handle theme changes reactively
- Use TypeScript for better type safety
- Test integration with React Testing Library
- Consider lazy loading for large applications