Blind AgentsIniciar sesión →
Blind Agents

Widget de Blind Agents

Guía de instalación e integración

The Blind Agents widget adds an AI-powered bug reporter, live webchat, and product guides to any website or app — with a single script tag or npm package.

Inicio rápido

Two widgets, one platform. Paste before </body>:

Bug reporter (report.js)

html
<script
  src="https://cdn.blindagents.com/report.js"
  data-api-key="YOUR_API_KEY"
  data-primary-color="#e11d48"
  data-title="Help Center"
  data-report-btn-text="Report an issue"
  data-btn-emoji="🔴"
  data-icon-url=""
  data-btn-tooltip="Report an issue"
  data-empty-text="No issues reported yet."
  data-user-whatsapp=""
  data-external-id=""
  data-position="bottom-right"
  data-anchor=""
  data-bubble-size="56"
  data-panel-width=""
  data-panel-height="">
</script>

AI chat widget (chat.js)

html
<script
  src="https://cdn.blindagents.com/chat.js"
  data-api-key="YOUR_API_KEY"
  data-agent-id="YOUR_AGENT_UUID"
  data-primary-color="#4f46e5"
  data-btn-emoji="💬"
  data-icon-url=""
  data-btn-tooltip="Chat with us"
  data-user-whatsapp=""
  data-external-id=""
  data-position="bottom-right"
  data-anchor=""
  data-bubble-size="56"
  data-panel-width=""
  data-panel-height=""
  data-font-size="14px"
  data-font-family="System"
  data-notification-sound="true">
</script>
✓ Tip:Replace YOUR_AGENT_UUID with your agent's ID from Agents.

¿Usas otro stack? Tenemos instrucciones para cada plataforma.

HTML / Cualquier sitio

1

Copy your API key from Settings → API Keys

Generate a key if you haven't already. It starts with ba_.

2

Paste the script tag before </body> in your HTML

html
<script
  src="https://cdn.blindagents.com/report.js"
  data-api-key="YOUR_API_KEY"
  data-primary-color="#e11d48"
  data-title="Help Center"
  data-report-btn-text="Report an issue"
  data-btn-emoji="🔴"
  data-icon-url=""
  data-btn-tooltip="Report an issue"
  data-empty-text="No issues reported yet."
  data-user-whatsapp=""
  data-external-id=""
  data-position="bottom-right"
  data-anchor=""
  data-bubble-size="56"
  data-panel-width=""
  data-panel-height="">
</script>
3

Done — the widget launcher appears on your site

ℹ Info:The script loads asynchronously and won't block your page render.

React — Vite / CRA

1

Install the npm package

bash
npm install @duvandroid/react-blind-agents
2

Add the widget to your App root

tsx
// src/App.tsx
import { BlindAgents } from '@duvandroid/react-blind-agents';

export default function App() {
  return (
    <BlindAgents apiKey="YOUR_API_KEY">
      {/* Report widget — bug reporter */}
      <BlindAgents.Report
        primaryColor="#e11d48"
        title="Help Center"
        reportBtnText="Report an issue"
        btnEmoji="🔴"
        position="bottom-right"
        bubbleSize={56}
      />

      {/* Chat widget — AI agent */}
      <BlindAgents.Chat
        agentId="YOUR_AGENT_UUID"
        primaryColor="#4f46e5"
        position="bottom-left"
        bubbleSize={56}
      />
    </BlindAgents>
  );
}
3

That's it

✓ Tip:Place <BlindAgentsWidget> once at the App root — it renders nothing in the DOM tree, only injects the script.

Next.js

1

Install the npm package

bash
npm install @duvandroid/react-blind-agents
2

App Router — add to layout.tsx

tsx
// app/layout.tsx
import { BlindAgentsWidget } from '@duvandroid/react-blind-agents/next';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
        <BlindAgentsWidget
          apiKey="YOUR_API_KEY"
          primaryColor="#e11d48"
          title="Help Center"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}
ℹ Info:Use the /next subpath — it uses next/script internally for correct hydration.
2

Pages Router — add to _app.tsx

tsx
// pages/_app.tsx
import type { AppProps } from 'next/app';
import { BlindAgentsWidget } from '@duvandroid/react-blind-agents/next';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      <BlindAgentsWidget apiKey="YOUR_API_KEY" primaryColor="#e11d48" />
    </>
  );
}

Shopify

1

Open your theme code editor

In your Shopify Admin → Online Store → Themes → Edit code.

2

Open theme.liquid

Find the file under Layout → theme.liquid.

3

Paste the snippet before </body>

liquid
{%- comment -%} Paste in theme.liquid before </body> {%- endcomment -%}
<script
  src="https://cdn.blindagents.com/report.js"
  data-api-key="YOUR_API_KEY"
  data-primary-color="#e11d48"
  data-title="Help Center"
  data-report-btn-text="Report an issue"
  data-btn-emoji="🔴"
  data-btn-tooltip="Report an issue"
  data-user-whatsapp="{{ customer.phone | default: '' }}">
</script>
✓ Tip:The {{ customer.phone }} Liquid variable automatically passes the logged-in customer's phone number — skipping the identity verification step for authenticated shoppers.
4

Save — the widget appears on your storefront immediately

No app install required. Works on any Shopify plan including Online Store 2.0 themes.

ℹ Info:For Shopify Plus headless stores (Hydrogen / Remix), use the React or npm instructions above.

Lovable

1

Open your Lovable project

Lovable generates a React/Vite app — use the npm package for the cleanest integration.

2

Ask Lovable to install the package

"Install @duvandroid/react-blind-agents and add a BlindAgentsWidget to App.tsx with apiKey="YOUR_API_KEY" and primaryColor="#e11d48""

3

Or add it manually via the code editor

html
<!-- Add inside index.html <body> or in a custom HTML component -->
<script
  src="https://cdn.blindagents.com/report.js"
  data-api-key="YOUR_API_KEY"
  data-primary-color="#e11d48"
  data-title="Help Center"
  data-report-btn-text="Report an issue"
  data-btn-emoji="🔴">
</script>

Paste in index.html before </body>, or use the React snippet in App.tsx.

Wix

Option A — Custom Code (no-code, recommended)

1

Go to Settings → Custom Code

In the Wix dashboard: Settings → Custom Code → + Add Custom Code.

2

Paste the script tag

html
<script
  src="https://cdn.blindagents.com/report.js"
  data-api-key="YOUR_API_KEY"
  data-primary-color="#e11d48"
  data-title="Help Center"
  data-report-btn-text="Report an issue"
  data-btn-emoji="🔴"
  data-icon-url=""
  data-btn-tooltip="Report an issue"
  data-empty-text="No issues reported yet."
  data-user-whatsapp=""
  data-external-id=""
  data-position="bottom-right"
  data-anchor=""
  data-bubble-size="56"
  data-panel-width=""
  data-panel-height="">
</script>
3

Set placement to Body – end and apply to All Pages

ℹ Info:Choose Load once to avoid duplicate injections across page navigations.

Option B — Velo (code)

js
// Wix Velo — paste in Site > Add Code to Pages > Add Code to All Pages (body end)
// Or use Wix > Settings > Custom Code > Add custom code

// Option A: Custom Code panel (no-code)
// Paste the raw <script> tag in Settings → Custom Code → Body - end

// Option B: Velo (code)
import wixWindow from 'wix-window';

$w.onReady(() => {
  const script = document.createElement('script');
  script.src = 'https://cdn.blindagents.com/report.js';
  script.setAttribute('data-api-key', 'YOUR_API_KEY');
  script.setAttribute('data-primary-color', '#e11d48');
  script.setAttribute('data-title', 'Help Center');
  script.defer = true;
  document.body.appendChild(script);
});

WordPress

Choose the method that fits your setup:

Webflow

1

Open Site Settings → Custom Code

In the Webflow designer: Project Settings → Custom Code.

2

Paste in the Footer Code section

html
<!-- Webflow: Site Settings → Custom Code → Footer Code -->
<script
  src="https://cdn.blindagents.com/report.js"
  data-api-key="YOUR_API_KEY"
  data-primary-color="#e11d48"
  data-title="Help Center"
  data-report-btn-text="Report an issue"
  data-btn-emoji="🔴"
  data-btn-tooltip="Report an issue"
  defer>
</script>
3

Publish your site

✓ Tip:For page-specific installation, open the page settings and paste in that page's Before </body> tag field instead.

Squarespace

⚠ Warning:Code Injection is available on Business plan and above.
1

Go to Settings → Advanced → Code Injection

In the Squarespace dashboard sidebar.

2

Paste in the Footer field

html
<!-- Squarespace: Settings → Advanced → Code Injection → Footer -->
<script
  src="https://cdn.blindagents.com/report.js"
  data-api-key="YOUR_API_KEY"
  data-primary-color="#e11d48"
  data-title="Help Center"
  data-report-btn-text="Report an issue"
  data-btn-emoji="🔴"
  defer>
</script>
3

Save — the widget loads on every page

For per-page injection, use Page Settings → Advanced → Page Header Code Injection.

Ghost

1

Go to Ghost Admin → Settings → Code Injection

Available on all Ghost plans.

2

Paste in the Site Footer field

html
<!-- Ghost: Settings → Code Injection → Site Footer -->
<script
  src="https://cdn.blindagents.com/report.js"
  data-api-key="YOUR_API_KEY"
  data-primary-color="#e11d48"
  data-title="Help Center"
  data-report-btn-text="Report an issue"
  data-btn-emoji="🔴"
  defer>
</script>
3

Save — done

ℹ Info:Ghost also supports injecting code per-post via the post editor's Code Injection option in the post settings sidebar.

Bubble

1

Open your Bubble app settings

Settings → SEO / metatags tab.

2

Paste in the Script/meta tags in header field

html
<!-- Bubble: Settings → SEO / metatags → Script/meta tags in header
     Or use an HTML element on the page with the script tag -->
<script
  src="https://cdn.blindagents.com/report.js"
  data-api-key="YOUR_API_KEY"
  data-primary-color="#e11d48"
  data-title="Help Center"
  data-report-btn-text="Report an issue"
  data-btn-emoji="🔴"
  defer>
</script>

Alternatively, add an HTML element on any page and paste the script tag there.

3

Deploy to live — the widget appears on your app

✓ Tip:In Bubble's test environment the script still loads — you can verify it works before going live.

Framer

1

Open Site Settings → General → Custom Code

Click the gear icon in the top-right of the Framer editor.

2

Paste in the End of body tag section

html
// Framer: Site Settings → General → Custom Code → End of <body>
<script
  src="https://cdn.blindagents.com/report.js"
  data-api-key="YOUR_API_KEY"
  data-primary-color="#e11d48"
  data-title="Help Center"
  data-report-btn-text="Report an issue"
  data-btn-emoji="🔴"
  defer>
</script>
3

Publish — the widget loads on your live Framer site

ℹ Info:Custom Code requires a Framer paid plan. For page-specific injection use the page's own Custom Code section.

Google Tag Manager

GTM lets you deploy the widget to any site without touching the source code — useful for marketing teams or sites managed by multiple people.

1

Create a new Custom HTML Tag

In GTM: Tags → New → Tag Configuration → Custom HTML.

2

Paste the custom HTML snippet

js
// Google Tag Manager → Tags → New → Custom HTML
<script>
(function() {
  var el = document.createElement('script');
  el.src = 'https://cdn.blindagents.com/report.js';
  el.setAttribute('data-api-key', 'YOUR_API_KEY');
  el.setAttribute('data-primary-color', '#e11d48');
  el.setAttribute('data-title', 'Help Center');
  el.setAttribute('data-report-btn-text', 'Report an issue');
  el.setAttribute('data-btn-emoji', '🔴');
  el.defer = true;
  document.head.appendChild(el);
})();
</script>
// Trigger: All Pages — Page View
3

Set trigger to All Pages

Under Triggering, select All PagesPage View.

4

Submit and publish the container

✓ Tip:GTM's Preview mode lets you test the widget before publishing to production.

Slack

Get real-time Slack notifications for every Blind Agents event — new tickets, status changes, resolved issues, and new contacts. There are two approaches: a simple Slack Incoming Webhook, or a full server middleware that verifies signatures.

1

Create a Slack Incoming Webhook

1. Go to api.slack.com/appsCreate New App → From scratch.

2. Under Features → Incoming Webhooks, enable it and click Add New Webhook to Workspace.

3. Select the channel (e.g. #bugs) and copy the webhook URL.

✓ Tip:Test your Slack webhook URL with a quick curl before wiring it up.
bash
curl -X POST https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK \
  -H "Content-Type: application/json" \
  -d '{
    "text": "New Blind Agents ticket: Button not working on checkout",
    "blocks": [{
      "type": "section",
      "text": { "type": "mrkdwn", "text": "*New ticket:* Button not working on checkout" }
    }]
  }'
2

Create a Blind Agents webhook pointing to your server

In Blind Agents → Webhooks → Add webhook, enter your server endpoint URL (e.g. https://yourserver.com/webhooks/blind-agents) and select the events to subscribe to.

ℹ Info:Blind Agents sends this payload to your endpoint on every event:
json
// Example payload Blind Agents sends to your webhook URL
{
  "id": "evt_01HXYZ...",
  "event": "ticket.created",
  "created_at": "2026-04-09T03:00:00Z",
  "data": {
    "id": "tkt_01HXYZ...",
    "title": "Button not working on checkout",
    "status": "open",
    "priority": "high",
    "type": "bug",
    "contact": { "name": "Jane Doe", "email": "jane@example.com" },
    "page_url": "https://yoursite.com/checkout"
  }
}
3

Build the middleware to forward events to Slack

This Node.js/Express handler verifies the signature then forwards a message to Slack:

ts
// Express.js handler that forwards Blind Agents events to Slack
import express from 'express';
import crypto from 'crypto';

const app = express();
app.use(express.raw({ type: 'application/json' })); // raw body for signature verification

const BA_SECRET  = process.env.BLIND_AGENTS_WEBHOOK_SECRET;
const SLACK_URL  = process.env.SLACK_WEBHOOK_URL;

function verify(rawBody, signature) {
  const parts = Object.fromEntries(signature.split(',').map(p => p.split('=')));
  const expected = crypto.createHmac('sha256', BA_SECRET)
    .update(`${parts.t}.${rawBody}`).digest('hex');
  const valid   = crypto.timingSafeEqual(Buffer.from(parts.v1, 'hex'), Buffer.from(expected, 'hex'));
  const recent  = Date.now() / 1000 - Number(parts.t) < 300;
  return valid && recent;
}

app.post('/webhooks/blind-agents', async (req, res) => {
  const sig = req.headers['x-blindagents-signature'];
  if (!verify(req.body.toString(), sig)) return res.sendStatus(401);

  const { event, data } = JSON.parse(req.body.toString());

  // Map events to Slack messages
  const messages = {
    'ticket.created':        `🎫 *New ticket:* <${data.page_url}|${data.title}> — ${data.priority} priority`,
    'ticket.status_changed': `🔄 *Ticket updated:* ${data.title} → ${data.status}`,
    'ticket.resolved':       `✅ *Ticket resolved:* ${data.title}`,
    'contact.created':       `👤 *New contact:* ${data.name} (${data.email})`,
  };

  const text = messages[event] ?? `📡 Blind Agents event: ${event}`;

  await fetch(SLACK_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ text }),
  });

  res.sendStatus(200);
});
4

Use Block Kit for rich Slack messages (optional)

Replace the plain text message with a structured Block Kit layout including a direct link to the ticket:

ts
// Rich Slack message with Block Kit for ticket.created
const block = {
  blocks: [
    {
      type: "header",
      text: { type: "plain_text", text: "🎫 New Bug Report" }
    },
    {
      type: "section",
      fields: [
        { type: "mrkdwn", text: `*Title:*\n${data.title}` },
        { type: "mrkdwn", text: `*Priority:*\n${data.priority}` },
        { type: "mrkdwn", text: `*Reporter:*\n${data.contact?.name ?? 'Anonymous'}` },
        { type: "mrkdwn", text: `*Page:*\n${data.page_url ?? '—'}` },
      ]
    },
    {
      type: "actions",
      elements: [{
        type: "button",
        text: { type: "plain_text", text: "View ticket" },
        url: `https://www.blindagents.com/tickets/${data.id}`,
        style: "primary"
      }]
    }
  ]
};

n8n

n8n is an open-source workflow automation tool. Use it to connect Blind Agents events to Slack, email, Jira, Notion, Google Sheets, or any other service — without writing a server from scratch.

1

Add a Webhook trigger node in n8n

1. In n8n, create a new workflow.

2. Add a Webhook node as the trigger.

3. Set Method to POST and copy the generated URL.

js
// 1. In n8n, add a "Webhook" trigger node
// 2. Copy the generated webhook URL
// 3. In Blind Agents → Webhooks, create a new webhook with that URL
// 4. Select the events you want (e.g. ticket.created, ticket.status_changed)
// 5. Connect downstream n8n nodes to process the data
2

Register the n8n URL as a Blind Agents webhook

In Blind Agents → Webhooks → Add webhook:

• Paste the n8n webhook URL.

• Select the events you want (e.g. ticket.created, ticket.resolved).

• Copy the signing secret — you'll need it in the next step.

3

Add a Code node to verify the signature

This step is optional but strongly recommended. Add a Code node after the webhook trigger and paste this verification logic:

js
// n8n Code node — verify the Blind Agents signature
const crypto = require('crypto');

const secret    = $env.BLIND_AGENTS_SECRET;          // store in n8n Credentials
const signature = $input.first().headers['x-blindagents-signature'];
const rawBody   = JSON.stringify($input.first().body);

const parts = Object.fromEntries(signature.split(',').map(p => p.split('=')));
const msg   = `${parts.t}.${rawBody}`;
const hmac  = crypto.createHmac('sha256', secret).update(msg).digest('hex');

const isValid  = crypto.timingSafeEqual(Buffer.from(parts.v1, 'hex'), Buffer.from(hmac, 'hex'));
const isRecent = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;

if (!isValid || !isRecent) throw new Error('Invalid signature — aborting workflow');

return $input.all(); // pass through to next node
✓ Tip:Store BLIND_AGENTS_SECRET in n8n → Credentials → Custom API — never hardcode secrets.
4

Connect downstream nodes

Use expressions like {{ $json.body.data.title }} to access ticket fields. Example workflow sending to Slack:

js
// n8n workflow: Blind Agents → Slack (3 nodes)

// Node 1 — Webhook trigger (auto-generated URL, POST method)

// Node 2 — Code (signature verification, see above)

// Node 3 — Slack node (Send Message)
//   Channel: #bugs
//   Message text (expression):
"🎫 New ticket: {{ $json.body.data.title }}
Priority: {{ $json.body.data.priority }}
Reporter: {{ $json.body.data.contact.name }}
Page: {{ $json.body.data.page_url }}"
5

Always end with a Respond to Webhook node

js
// Always add an "Respond to Webhook" node at the end
// Response Code: 200
// Response Body: { "ok": true }
// This tells Blind Agents the delivery succeeded.
// If your workflow errors before this node, Blind Agents will mark the delivery as failed.
⚠ Warning:Without a 200 response, Blind Agents will mark the delivery as failed and may retry — always respond before the workflow ends.

Configuration Reference

All data-* attributes below work on both report.js and chat.js unless noted. React / Next.js props use camelCase equivalents (e.g. primaryColor, panelWidth).

Mounting inside a DOM element — set data-anchor to a CSS selector (e.g. #my-panel). The widget mounts inside that element with position:absolute instead of the default position:fixed.

Custom position — pass a JSON object to data-position: '{"bottom":"20px","right":"80px"}'. Presets: bottom-right · bottom-left · top-right · top-left.

data-api-key
Requiredboth

Your Blind Agents public API key (ba_...)

data-agent-id
Requiredchat

Agent UUID to connect the chat to (chat.js only)

data-user-whatsapp
both

Pre-fill WhatsApp number (country code required, e.g. 573114088900) — skips OTP verification

data-external-id
both

Your internal user / account ID — links sessions to your own CRM records

data-primary-color
both

Accent color for the widget UI (any CSS color)

data-btn-emoji
both

Emoji shown on the floating launcher button

data-icon-url
both

URL of an image to use as the launcher icon (overrides data-btn-emoji)

data-btn-tooltip
both

Tooltip text on the launcher button

data-title
report

Panel header title (report.js)

data-report-btn-text
report

"Report" button label inside the panel (report.js)

data-empty-text
report

Text shown when there are no reports (report.js)

data-font-size
chat

Chat font size preset e.g. "14px" (chat.js)

data-font-family
chat

Chat font family: "System" | "Serif" | "Mono" | "Rounded" (chat.js)

data-notification-sound
chat

Enable/disable notification sound on incoming messages — "true" (default) or "false" (chat.js)

data-position
both

Widget position: "bottom-right" | "bottom-left" | "top-right" | "top-left" | JSON object e.g. '{"bottom":"20px","right":"80px"}'

data-anchor
both

CSS selector of a DOM element to mount the widget inside (e.g. "#my-panel"). Element gets position:relative automatically.

data-bubble-size
both

Diameter of the floating launcher button in px (default: 56)

data-panel-width
both

Width of the open widget panel (any CSS length, e.g. "380px")

data-panel-height
both

Height of the open widget panel (any CSS length, e.g. "600px")

React / npm prop names

The npm package uses camelCase props that map 1:1 to the data attributes:

data-api-keyapiKey
data-primary-colorprimaryColor
data-titletitle
data-report-btn-textreportBtnText
data-btn-emojibtnEmoji
data-btn-tooltipbtnTooltip
data-empty-textemptyText
data-user-whatsappuserWhatsapp
data-external-idexternalId

npm package

@duvandroid/react-blind-agents

React component wrapper for the Blind Agents widget

View on npm
bash
npm install @duvandroid/react-blind-agents

Sigue explorando