Skip to main content

Widget Integration

Embed pre-built crisis resource UI with progressive disclosure.

Step 1: Detect Risk (Server-Side)

First, call /v1/evaluate from your backend. The response includes a widget_url with pre-matched scopes:

curl -X POST https://api.nope.net/v1/evaluate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [{"role": "user", "content": "I feel hopeless"}],
    "config": {"user_country": "US"}
  }'

Step 2: Show Widget (Client-Side)

On your frontend, show the widget when risk is detected:

// Client-side: Show widget based on server response
if (response.severity !== 'none') {
  const iframe = document.createElement('iframe');
  iframe.src = response.widgetUrl;  // Use the pre-built URL from evaluate response
  iframe.width = '100%';
  iframe.height = '400';
  iframe.style.border = 'none';
  container.appendChild(iframe);
}

Tip: The widget_url from the evaluate response has scopes pre-matched to the detected risk. You can also build URLs manually using the parameters below.

Direct Widget Parameters

You can also construct widget URLs directly:

https://widget.nope.net/resources?country=US&scopes=suicide,crisis&theme=dark
ParameterTypeDescription
countrystringISO country code (e.g., "US", "GB") or "auto" for IP detection
scopesstringComma-separated service scopes (WHAT it helps with): suicide, crisis, mental_health, domestic_violence, etc.
populationsstringComma-separated populations (WHO it serves): veterans, lgbtq, youth, elderly, etc.
themestringlight or dark (default: light)
pickerbooleanShow/hide country picker (default: true)
limitnumberMaximum number of resources to display
dismissiblebooleanShow close button (emits 'dismiss' event)
querystringNatural language context for intelligent resource ranking (requires scopes)

Widget Events (PostMessage)

Listen for events from the widget:

window.addEventListener('message', (e) => {
  // Security: verify origin
  if (e.origin !== 'https://widget.nope.net') return;
  if (e.data?.source !== 'nope-widget') return;

  switch (e.data.type) {
    case 'ready':
      // Widget loaded
      break;

    case 'resize':
      // Auto-resize iframe
      iframe.style.height = e.data.height + 'px';
      break;

    case 'countryChange':
      // User selected different country
      console.log('Country changed to:', e.data.country);
      break;

    case 'resourceClick':
      // User clicked a resource
      console.log('Clicked:', e.data.resource);
      break;

    case 'dismiss':
      // User clicked dismiss (requires dismissible=true)
      iframe.remove();
      break;
  }
});

When to Use Widget vs. Custom UI

ScenarioRecommendation
Quick integrationUse the widget with direct URL params
Brand-specific stylingBuild custom UI from crisis_resources[] (widget uses fixed accessible colors)
Mobile appBuild native UI from crisis_resources[]
Need analyticsCustom UI or listen to widget events

Single Resource Embed

Display a specific crisis resource by its database UUID. Useful for embedding a particular helpline on a partner website without the full resource list.

https://widget.nope.net/resource/{database-uuid}

# Example:
https://widget.nope.net/resource/c051c06a-119f-4823-af66-894d9b934b5f

Example JavaScript:

// Single resource embed - display a specific helpline by database ID
const iframe = document.createElement('iframe');
iframe.src = 'https://widget.nope.net/resource/c051c06a-119f-4823-af66-894d9b934b5f';
iframe.width = '400';
iframe.height = '300';
iframe.style.border = 'none';
container.appendChild(iframe);
FeatureDetails
AuthPublic (no API key required)
FallbackRedirects to /resources if resource not found
DisplayShows name, description, contact buttons, and open/closed status
Dark modeSupported via ?theme=dark

Getting resource IDs: Resource IDs are UUIDs from the database. You can get them via GET /v1/resources/:id or from the dashboard admin UI.

Privacy

The widget does not track users:

  • No analytics or tracking pixels
  • No cookies
  • Click events only sent to parent page via postMessage

Next Steps