Docs On your website

The widget on your website

You decide how you offer the widget to your visitors. For most approaches it comes down to one snippet of code you add to a page; it's live within fifteen minutes. This page brings everything together: how to put Vragen.ai on your site, how to style it to match your brand and how to include it in your Content Security Policy.

Using WordPress or Drupal? There is a dedicated WordPress plugin that synchronizes your content and places the widget as a block, and a Drupal module that replaces Drupal search with semantic search.

How to offer the widget

Everything starts with a deployment: a variant of the widget that you create in the vragen.ai dashboard. You can create as many as you like, for example one for your website and one for your intranet, each with its own example questions, texts and styling. For each deployment, the dashboard gives you the corresponding code or link.

When creating one, you make two choices: how the window appears, and how you install it on your site.

How the window appears

You configure this on the deployment itself. If you change it later, the code on your site doesn't need to change with it; your visitors see the new setting within about five minutes. You can choose from:

  • On your own page (inline). The window sits right within your content, like on the vragen.ai homepage.

  • As an overlay. The window opens on top of your page, for example after clicking a button.

  • As a side panel. The window slides in from the side of the screen.

  • As a standalone page. vragen.ai hosts a complete page with just the widget; you point to it with a link.

  • In your existing search field. Autocomplete shows suggestions as someone types. The Search Add-on places an AI summary above your regular search results.

How to put it on your site

A link to a hosted page. The fastest start, without installing anything. Choose the "standalone page" form for the deployment; you then get a URL that you attach to a button or link on your site:

<a href="https://yourorganization.vragen.ai/deployment/[deployment-name]" target="_blank">Ask your question</a>

Useful if you don't have access to your site's templates yet, for a demo or for a link on your intranet.

An embed script. This puts the window directly into a page. You place this script and an empty div element where the window should appear:

<script src="https://yourorganization.vragen.ai/embed.js?deployment=[deployment-name]"></script>
<div id="vragenai-app"></div>

The script loads from your own vragen.ai subdomain, and the deployment parameter determines which variant appears. Whether the window opens inline, as an overlay or as a side panel follows from that deployment's settings. You need access to your page's HTML for this.

As a smart addition to your search engine. Want to improve your existing search field instead of showing a separate window? Then you connect vragen.ai to your current search field with a separate script (embed-autocomplete.js) that the dashboard prepares for you. This belongs to the "Autocomplete" and "Search Add-on" forms.

Via the API. For custom builds there is a REST API. You send a question with context to vragen.ai and get an answer with sources back. Live streaming of answers works via the open AG-UI protocol, which vragen.ai supports, so you can recreate the widget experience in your own interface. This is how you build vragen.ai into your own system, for example a customer portal, knowledge base or helpdesk.

For internal use cases, you can put a deployment behind a login so that only employees can use the widget.

Parameters on the embed script

Almost everything is set in your deployment's settings, not in the code on your site. That way the embed does not have to change when you adjust something. A few things you do pass per page in the script URL. These are the parameters you need for that:

Parameter What for
deployment Which variant of the widget appears. Required.
locale The interface language, for example locale=en. Overrides the deployment's language.
forcedFilters Limits the answers to part of your knowledge base.
containerSelector Which element the widget renders in, when it is not #vragenai-app. Needed as soon as a page holds more than one widget.

forcedFilters is meant for one situation: you have several sites or subsites working from the same knowledge base, and each site should only show its own content. Every site then carries the same script and only the parameter varies:

<script src="https://yourorganization.vragen.ai/embed.js?deployment=[deployment-name]&forcedFilters=source:work.example.com"></script>

You filter on a metadata field of your documents, so the field has to exist in your knowledge base (see Your knowledge base in the app). Separate multiple values with a |, multiple filters with a comma, and use != to exclude instead:

forcedFilters=source:a.example.com|b.example.com,type!=archive

Note: this filter sits in the URL, so a visitor can see and change it. Use it to keep the answers on a page relevant, not to shield content. If content really must stay out of reach for a group of visitors, use a separate deployment with its own knowledge scope.

You need containerSelector when you put two widgets on one page, for example an inline window next to the search results and a side panel that is ready for your visitor on every page. By default every widget looks for the element #vragenai-app and renders in the first one it finds. Two widgets with that default therefore end up in the same element, and the second overwrites the first: one of the two stays empty. So give the second widget its own element and point to it in the script URL. Encode the hash as %23, otherwise the browser reads the rest of the URL as an anchor and the parameter never arrives:

<script src="https://yourorganization.vragen.ai/embed.js?deployment=[deployment-name]&containerSelector=%23vragenai-side-panel"></script>
<div id="vragenai-side-panel"></div>

If you style that widget with your own CSS, use this ID there too instead of #vragenai-app.

Does the API of your environment require credentials? Then there are extra parameters that send the widget's calls to a proxy on your own domain. How that works is covered in The widget in a locked-down environment.

Sources with an answer

Under every answer are the sources the agent cited. When a visitor clicks a source, that page opens with the passage the agent used highlighted. That way, anyone can see in one click where the answer comes from.

Highlighting doesn't work on every website. If the website doesn't support it, the page opens without highlighting.

Opening the widget from your own page

An overlay or side panel does not have to open through the built-in button only. Any button or link on your site can open the assistant and hand it a question right away. Put a button "Which documents do I need?" next to your application form, for example. Your visitor clicks and sees the answer appear, without having to type anything.

With an attribute, no JavaScript. If your deployment opens through an element of your own (the "CSS selector" or "Link / URL" trigger), put data-vragenai-question on that element. On a click the window opens and the widget asks that question straight away:

<button class="vragenai-trigger" data-vragenai-question="Which documents do I need?">Which documents do I need?</button>

Without the attribute, the same element simply opens the window.

With your own JavaScript. Once the widget has loaded, your page has a window.Vragenai object with these functions:

Function What it does
open() Opens the window.
close() Closes the window.
toggle() Opens the window when it is closed, and closes it when it is open.
reset() Clears the conversation and any chosen filters, so the visitor starts over.
ask('question') Opens the window and asks that question.

These functions only exist for the "Overlay" and "Side panel" forms, and only once the widget has loaded. So check that the function is there first:

document.querySelector('#application-help').addEventListener('click', () => {
  if (typeof window.Vragenai?.ask === 'function') {
    window.Vragenai.ask('Which documents do I need?');
  }
});

With two widgets on the page, the one that loaded last responds by default. To address one of them, pass the element that widget renders in, with the same selector as in containerSelector: window.Vragenai.open({ container: '#vragenai-side-panel' }), or for a question window.Vragenai.ask('Which documents do I need?', { container: '#vragenai-side-panel' }).

Styling the widget

The widget should look like it belongs to your website. You adjust colors, font and layout with your own CSS, and that works in every plan: those rules live in your own stylesheet, so no plan limit applies. Prefer to do it from the app? That works in every plan too: in your integration settings you add your own CSS, HTML or JavaScript and hide the vragen.ai branding inside the widget.

The widget renders inline in your page, so not in an iframe. All styling is scoped: the widget doesn't leak CSS into the rest of your site, and your site's CSS won't accidentally break the widget. If you want to change something, you do so deliberately with your own rules. Three starting points:

  • The #vragenai-app element. Put this ID in your selectors; that way your rules win over the widget CSS.

  • CSS variables. The widget uses custom properties (such as --vragenai-color-primary, the primary color) for colors and other base values. Set them on #vragenai-app and the whole widget follows along.

  • BEM classes. Every component has its own class, such as vragenai-question-form__input for the input field. Use these to style one specific component.

There is no published list of all variables and classes. Inspect the widget in your browser (right-click, "Inspect") to see which ones apply to a component.

Example:

#vragenai-app {
  --vragenai-color-primary: #1d4ed8; /* your brand color */
  font-family: "Your brand font", sans-serif;
}

#vragenai-app .vragenai-question-form__input {
  font-size: 1.0625rem;
}

That's how we do it ourselves: the widget on the vragen.ai homepage is styled to our own brand with this kind of CSS, right down to a brand gradient as the border around the input field.

Content Security Policy

Many organizations, especially in government and healthcare, secure their website with a Content Security Policy (CSP): a header that determines which external sources the browser may load. The widget is easy to include, because it only needs one domain.

Everything comes from your own vragen.ai subdomain. Specifically:

  • Scripts: embed.js and the widget's JavaScript bundle

  • Stylesheet: one CSS file

  • API requests: asking questions and streaming answers

  • Images: images shown by the widget also come from your own subdomain

There are no external CDNs, fonts, trackers or iframes. The widget does set inline styles on a few components; the example below takes that into account.

Replace yourorganization.vragen.ai with your own subdomain and add these sources to your existing policy:

script-src  'self' https://yourorganization.vragen.ai;
style-src   'self' https://yourorganization.vragen.ai 'unsafe-inline';
connect-src 'self' https://yourorganization.vragen.ai;
img-src     'self' https://yourorganization.vragen.ai;

The 'unsafe-inline' in style-src is needed for the widget's inline styles. If you don't want to allow that site-wide, use the more fine-grained style-src-attr directive. frame-src is not needed: the widget renders directly in your page, without an iframe.

Working with a nonce?

If your policy uses nonces instead of 'unsafe-inline', pass that nonce to the embed script. The widget then puts it on the script and the stylesheet it adds itself, so those pass your policy without you having to open up 'unsafe-inline':

<script src="https://yourorganization.vragen.ai/embed.js?deployment=[deployment-name]"
        data-script-nonce="NaN"
        data-style-nonce="NaN"></script>

If both are the same value, a single data-nonce will do. And if the nonce is already on the script as a plain nonce attribute, the widget uses that.

One thing remains: the widget also sets a style attribute on a few elements, and a nonce does not apply to attributes. Keep style-src-attr 'unsafe-inline' for those; that is a lot narrower than 'unsafe-inline' on your whole style-src.

Is your CSP still blocking something? You'll see it as an error in the browser console (F12). Email the error message to service@vragen.ai; we respond within one business day.

Frequently asked questions

Can I use multiple widgets on one page?
Yes, with separate deployments, each with its own configuration. Do give each widget its own element on the page with the containerSelector parameter (see "Parameters on the embed script" above); otherwise both render in the same element and one stays empty.

Can we customize the design ourselves?
Yes. In every plan you style the widget with your own CSS: colors, font and more (see "Styling the widget" above). You can also add your own CSS from the app, and that is also where you hide the vragen.ai branding for a fully white-label appearance. That works in every plan.

What if we don't have access to our site yet?
Start with the link to a hosted page. You can always switch to an embed later.

Need help?
Our team walks you through it step by step. Email service@vragen.ai or schedule an integration call.

Still have a question?

Ask it here. The answer comes from this documentation and points to the right page.

What exactly is vragen.ai?

Example answer by vragen.ai

vragen.ai lets visitors ask their question on your website and gives them a reliable answer straight from your own content, with the source included. You decide which sources the AI uses.

Source: How it works

This is an example. The interactive widget could not load here, for instance because of a script blocker or a slow connection.

You are talking to an AI assistant from vragen.ai. Why we mention this