Browse documentation

Guidly for builders

Documentation that matches the product.

Everything you need to embed Guidly, tune how it speaks for your brand, and ship confident in-product guidance without sending users to another tab.

What is Guidly?

Guidly is an AI assistant that lives inside a website or web application. A visitor opens the floating chatbot and asks a question. Guidly uses the current page and the content you configure as context to generate a response. In Tutorial mode, a response can include a guide that highlights controls and waits for the visitor to use them.

For example, a visitor on a reporting page can ask, “How do I export this report?” Guidly can point to the Export CSV button, explain what it does, and continue when the visitor clicks it. Your application still performs the export. Guidly supplies the explanation and visual guidance.

Who uses Guidly?#

  • Workspace owners and product teams connect an AI provider, customize the assistant, maintain product knowledge, and review how people use it.
  • Developers install the script, make important controls easy to identify, connect optional analytics events, and test the integration on the real application.
  • Visitors ask questions and follow guides inside the application they are already using. They do not need access to your Guidly dashboard.
  • Guidly staff create client workspaces, assign plans, and manage the separate assistant used on Guidly's public pages.

What you get#

The installed product includes a movable launcher, a chat panel, suggested questions, Question and Tutorial modes, on-page highlighting, and plan-dependent analytics. You control the title, greeting, colors, size, corner, preset Q&A, and plain-text knowledge from the dashboard.

You install the script once. Saved configuration is loaded when the widget initializes, so future copy, knowledge, and appearance changes need a save and a website reload, rather than a new script tag.

These guides describe the current implementation. Workspace access, commercial terms, and any production deployment arrangements are agreed with Guidly as described in the Terms. Before using personal data in a customer integration, review the deployment privacy requirements.

Understand the product

Guidly concepts
ConceptWhat it meansWhere it is managed
WorkspaceThe client account that owns one set of widget settings, provider keys, usage and reports.Guidly dashboard
LauncherThe floating button that opens the assistant. Its corner and size are configurable.Customize → Colors & placement
Embed keyThe public workspace identifier sent by the installed widget. It is included in the script tag.Integrations → Install & embed
Provider keyYour private Anthropic or OpenAI API credential, used on Guidly’s server for inference.Integrations → AI models & keys
Page contextA text-and-controls snapshot collected from the current browser document for each question.Collected by the widget
Preset Q&AQuestions that appear as suggestions, with owner-provided answers used as model context.Customize → Preset Q&A
Knowledge basePlain-text product facts and policies that supplement the current page.Customize → Knowledge base
GuideAn ordered sequence of selectors, titles and instructions, shown over the host application.Generated for a Tutorial request

Question mode and Tutorial mode#

Question mode is for explanations: “What does this setting do?” or “What is our cancellation policy?” The visitor stays in chat. Tutorial mode is for actions: “Show me how to change this setting.” If the response contains a usable guide, the chat closes while the spotlight and step card appear over the page.

A Tutorial request can still receive a text answer when the model cannot produce a suitable flow. A configured Q&A pair is context for the model, not a recorded or guaranteed sequence of clicks.

Customer widget, showcase, and dashboard guide#

The assistant you install on your website uses your workspace's settings and provider key. The assistant on Guidly's landing page is a separate showcase configuration. The built-in dashboard guide uses predefined local setup tasks and works before your provider key is connected. Changes to your client widget do not rebrand Guidly's own public assistant.

Current boundaries#

  • Guidly uses content from the browser document. It has no direct connection to your server source code, database, or private repository. Information rendered into the document can become part of the page context.
  • Guidance directs the user; it does not grant permissions, submit privileged server operations by itself, or verify that a business process succeeded.
  • Answers and selectors are generated by a model and can be incomplete or incorrect. Test representative tasks after meaningful UI or knowledge changes.
  • The standard request sends the current question and page context, not the complete previous chat transcript. Phrase follow-ups with enough context to stand on their own.
  • The widget targets the current document. Cross-origin iframes, controls inside shadow roots, and elements that have not mounted are outside ordinary selector targeting.

Your first working assistant

This walkthrough takes you from an existing client workspace to a verified installation. You need your Guidly login, access to a supported AI provider account, and someone who can add a script to your website.

If you do not have a workspace yet, contact Guidly to arrange access. Client accounts are provisioned by staff. The website's public chatbot is not your client account and does not configure an installation for you.

  1. Open your workspace. Sign in. Client accounts go directly to their own overview. Confirm that the workspace name and plan are the ones you intend to use.
  2. Connect inference. In Integrations → AI models & keys, choose an available model, select its provider, paste the provider key, and save it. If you changed the model, click Save model as well.
  3. Give the assistant useful context. In Customize, set the title and greeting. Add one complete Q&A pair and a short knowledge entry about a real task or policy. Click Save in the bar at the top.
  4. Install the workspace snippet. Copy it from Integrations → Install & embed into your website's shared layout. The script URL, API URL, and embed key should all come from that workspace.
  5. Verify an answer. Reload the actual website, open the launcher, and ask the question you configured. Check that the answer uses the intended facts.
  6. Verify a guide. On a page with a clearly labeled control, choose Tutorial and ask how to complete a small task. Check the highlight, description, and step advancement by performing the action yourself.
  7. Verify updates. Change the greeting or primary color in Customize, save, and reload the website. The update should appear using the same installed script.

How to know setup is complete#

You should see one launcher, the expected title and greeting, a successful answer, and a guide that points to a real control. The dashboard's missing-key Setup reminder should be gone. If your plan includes reports and collection is enabled, new requests should become visible in Analytics after refresh.

If something fails, use the troubleshooting workflow. It separates loading, workspace identity, provider access, configuration, and targeting issues.

Use your workspace

Find the right section#

Client dashboard sections
SectionUse it to
OverviewCheck your plan and monthly question allowance, then open the main workspace tools.
CustomizeEdit appearance, chat copy, preset Q&A, and knowledge. Changes remain drafts until saved.
IntegrationsConnect provider keys, save an AI model, and copy the installation snippet.
AnalyticsReview allowance and connection health on every plan, and the reports included in Growth or Scale.

On smaller screens, use the dashboard's top navigation. Staff may see additional client-management and marketing-assistant sections. Those controls are not available to a client account.

Get an on-screen setup walkthrough#

Open the launcher in your workspace to use Your dashboard guide. It offers these built-in tasks:

  • Show me how to customize my chatbot.
  • Show me how to edit my chatbot content.
  • Show me how to add Q&A questions.
  • Show me how to add a knowledge base.
  • Show me how to set up my AI API key.
  • Show me how to install the chatbot on my website.
  • Show me how to see my analytics.

In Tutorial mode, the task opens the relevant page and tab, waits for its controls, and highlights each step. You enter the information and choose when to save. Manual setup steps use Next so you can finish an edit before moving on. In Question mode, the assistant explains the steps without navigating.

Save or discard an existing customization draft before starting a task that needs another page or tab. After a guide finishes or is stopped, the task choices return. These setup tasks are handled locally by the signed-in dashboard and do not require your AI provider key.

Client and staff access#

A client login is scoped to its own workspace. Staff create workspaces, assign plans, activate or deactivate clients, regenerate embed keys, and delete clients. The Client Details card is staff-only. An embed key cannot be used as a dashboard login, and a provider key cannot be used in place of an embed key.

Create a workspace as staff#

  1. Open All Clients and choose New Client.
  2. Enter the client name and a unique URL-safe slug, then assign Starter, Growth, or Scale.
  3. Enter the owner's login email. Set a password of at least 10 characters, or leave the password blank to generate one.
  4. Create the client. If a password was generated, copy it from the welcome panel while it is shown and share the login credentials securely with the owner.
  5. Ask the owner to sign in and follow this quickstart. Creating a workspace does not also connect its provider account.

For an existing workspace, use the staff overview controls for plan and activation changes. Deactivation blocks client chat requests. Regenerating the public embed key requires replacing it in every installed snippet. Treat deletion as a separate destructive management operation, not a way to reset a demo.

Explore the live demo

The live demo shows the assistant in three sample applications. Their data and workflows are illustrative; the workspace names and examples do not represent customer relationships or endorsements. Demo edits do not change your own project. Use sample information when trying the AI chat, which makes real provider requests.

Demo workspaces
WorkspaceApplicationExample tasks
StudioCutCreative toolsEdit a clip, add captions and export the project; Balance the audio, style the picture and export the project; Fine-tune framing and pacing, preview the edit and export
NorthbeamAnalytics & insightsAnalyze revenue and account health, then export the trend; Investigate customer health and record a follow-up note; Compare recurring revenue, segment accounts and export a monthly report
Lumen MercantileCommerce & operationsCreate a customer order with products, quantities and shipping; Create and activate a discount with a minimum purchase; Review an at-risk order, fulfill it and export the order queue

Choose StudioCut, Northbeam, or Lumen Mercantile, then select Try a task to open the chatbot and start a suggested tutorial. Workspaces returns to the picker. Reset resets the active sample application; it does not promise to restore consumed guest turns. Cookie settings remains available in the demo navigation.

Which chatbot does the demo use?#

Signed-in clients can load their own workspace embed; staff can use the last client workspace they opened. Signed-out demo help uses Guidly's separately configured showcase provider key and guest limits. If the assistant is unavailable, the demo UI can still load, but AI help needs a configured provider. Guest limits are separate from a client workspace's monthly allowance.

The first mobile preview selects the middle workspace. You can switch to any of the three. A successful tutorial in a sample application demonstrates the guidance experience; it does not verify your own application's DOM, provider configuration, or product knowledge.

Connect an AI provider

Each client workspace brings its own provider credential. Guidly stores it encrypted on the server and uses it for the workspace's selected model. A client request does not fall back to a global provider key if that connection is missing.

Set up a provider and model#

  1. Open Integrations → AI models & keys. Review the model selector and the models your plan allows.
  2. Select the provider you want to configure: Anthropic or OpenAI. Create the key in that provider's account, then paste it into the secret-key field.
  3. Click Save Anthropic key or Save OpenAI key. The saved indicator and provider background show that a key is stored. The secret itself is not returned to the dashboard.
  4. If you chose a different AI model, click Save model. Changing the provider-key tab only changes which credential you are editing; it does not switch the model used for replies.
  5. Send a test question from your installed chatbot. Check Analytics for the current model's observed connection result if the request fails.

Both provider credentials can remain stored when your plan supports them. You can switch models without pasting the same saved key again. Your provider account still needs API credits, permissions, and access to the selected model. A subscription to a provider's separate consumer chat product is not a saved Guidly API credential.

Available models and plans#

Models configured in this version of Guidly
ModelProviderAvailable on
Claude Sonnet 4.6AnthropicStarter, Growth, Scale
Claude Opus 4.6AnthropicGrowth, Scale
GPT-5.4 MiniOpenAIGrowth, Scale
GPT-5.4OpenAIGrowth, Scale

The selector is the current source of available model choices for your workspace. These names describe what Guidly supports; they do not guarantee that your provider account has enabled every model.

Guidly workspace plans
PlanMonthly questionsModel selectionAnalytics
Starter5,000Claude Sonnet 4.6Usage counter
Growth25,000Supported Claude and OpenAI modelsPerformance analytics
ScaleNo fixed monthly cap; subject to fair use and agreed throughputSupported Claude and OpenAI modelsAdvanced analytics

This table explains the plan settings implemented in the application. Confirm the plan, availability, and commercial terms for your workspace with Guidly. It does not establish an uptime, throughput, or response-accuracy commitment.

Understand the two kinds of usage#

Your Guidly plan provides a monthly question allowance. Your AI provider bills its inference usage separately. Questions from all visitors to the same workspace share the Guidly allowance; requests for walkthroughs count too.

The allowance resets at the start of each UTC calendar month. The server reserves a question before inference to account for concurrent requests and releases the reservation when inference fails. Detailed analytics counts attempted requests, including some failures, so its Requests total can differ from the monthly usage counter.

Only Guidly staff can assign a different plan. Moving to Starter selects its supported default Claude model. It does not erase usage already recorded for the current month.

Setup reminders and replacing a key#

The Setup reminder beside Integrations means the effective saved model has no saved key for its provider. It is a presence check, not a live authentication test. A saved key can still be rejected, have no credits, lack model access, or hit provider limits.

To replace a key, select its provider, enter the replacement, and save. To remove it, use Remove key. Removing the key for the active model prevents replies until you save a usable key or choose another configured model. Provider-key changes do not require a new website snippet.

Customize your assistant

Open Customize to edit your workspace's widget. The four tabs share one draft and the same Save/Discard bar. Saved settings are loaded the next time your website's widget initializes.

Save, discard, and see the result#

  1. Make an edit. The bar at the top shows Unsaved changes.
  2. Use Save to write the settings, or Discard to reload the previously saved version.
  3. Reload the website where the chatbot is installed. You do not need to replace the installed script after a normal customization change.

Changing a tab in Customize keeps your draft. Save before leaving the editing workflow. If an older script sets data-color, data-position, or another explicit override, that override can prevent a matching dashboard setting from appearing. See configuration precedence.

Colors, size, and position#

Appearance settings
SettingWhat changesRange or default
Primary colorLauncher background, chat header, visitor message bubbles and send control. Light or dark foreground colors are chosen from the configured color.Six-digit hex; default #030712
Guide accentThe outline around the control being highlighted in a tutorial.Six-digit hex; default #030712
Button sizeThe floating launcher and the icon inside it.48–96px; default 64px
PositionThe configured screen corner for the launcher and chat panel.Bottom right, bottom left, top right or top left

Assistant reply bubbles remain neutral. Check text and icon contrast in your actual integration after changing colors. Visitors can drag the launcher to another corner. That preference is stored locally for the workspace and API host; it resets when you change the configured corner. If browser storage is unavailable, the saved workspace position is used.

Write the title and greeting#

The title appears in the panel header. The greeting is the first assistant message when the panel opens. Use the title to identify the help experience and the greeting to explain what people can ask.

Identify the AI assistant clearly in its title or greeting so visitors understand who is responding at the start of an interaction. For example: “I'm an AI assistant for this product. Ask about your reports, or choose Tutorial for on-page help. Check important answers before acting.” Match the wording to your actual capabilities and review the deployment guidance.

Workspace content limits
FieldLimit
Chat title120 characters
Greeting2,000 characters
Preset Q&A pairs12 pairs, with up to eight suggested question chips
Each preset question280 characters
Each preset answer2,000 characters
Knowledge base12,000 characters

Teach Guidly about your product

Guidly combines the current page with owner-provided Q&A and knowledge. Page context explains what the visitor can see and click. Your content supplies facts that the interface alone cannot answer: permissions, terminology, billing rules, product behavior, and support paths.

Create useful preset Q&A#

  1. Open Customize → Preset Q&A and choose Add question.
  2. Expand the new pair. Write the question the visitor would actually ask.
  3. Add a direct answer with the important conditions, then save.

Both fields need content; incomplete pairs are not retained by the server's sanitizer. Up to 12 pairs are saved, and the first eight non-empty questions can appear as suggestion chips. All saved pairs provide model context, including those not shown as chips.

Example Q&A for a fictional reporting product
QuestionExample answer
How do I export revenue?Open Reports, choose a reporting period, and select Export CSV. The download contains the data for that period.
Who can change the billing plan?Only workspace owners can change the billing plan. Contact your owner if you cannot access billing settings.
Why does my report look empty?Check the reporting period and filters first. If the selected period has no activity, try a period with known data.

These are examples for an invented product. Replace the facts with your actual behavior. Suggested questions submit a question to the assistant; they do not run a stored script or bypass the AI provider.

Build a clear knowledge base#

Use short topic headings and concrete statements. State who can do a task, where it starts, what the result means, and any exceptions. Keep one current version of a policy instead of several contradictory versions.

product-knowledge.txttext
PRODUCT: Acme Reports

Exporting revenue
- Open Reports, then choose the reporting period.
- Select Export CSV to download the displayed revenue data.
- Exports use the workspace's reporting currency.

Access
- Only workspace owners can change the billing plan.
- If an export fails, check that you can view the report first.

Support
- If the answer is not covered here, direct users to the Support page.
- Do not invent prices, refund rules, or permissions.

This example shows a structure, not facts about Guidly or your product. Review content with the people responsible for the product before saving it. Tone instructions and fallback suggestions are model context; they are not a deterministic policy engine.

Import a text file#

In Knowledge base, choose Import .txt or .md. The browser reads the text into the editor. Import replaces the current editor text and retains its first 12,000 characters. It does not merge documents or save automatically. Review the result and click Save.

This is plain-text context, not a website crawler or a searchable document-upload service. PDF, image, and spreadsheet extraction are not part of this import flow. Prepare a concise text or Markdown version first.

Maintain answers as the product changes#

After changing a feature, review its Q&A answer, knowledge entry, and visible UI labels together. Use Analytics → Needs attention to find unanswered questions, negative feedback, AI failures, and broken guides. Ask the same question on the relevant page after saving the revision.

Install the widget

The standard integration is one browser script. There is no framework package to install in the host application. Use the snippet from your workspace's Integrations → Install & embed tab, which contains the correct bundle URL, API base URL, and embed key.

HTML and shared layouts#

Add the script near the end of the body in the layout used by pages that need the assistant. Install it once per document. Do not add a second copy inside every page component.

layout.htmlhtml
<script
  async
  src="https://guidly.example/guidly-widget.js"
  data-guidly-key="YOUR_EMBED_KEY"
  data-api-url="https://guidly.example"
></script>

The async script initializes the widget, fetches public workspace settings, and mounts the launcher and chat panel into the host document. Open the launcher only after it appears; loading the script file and fetching settings are separate network operations.

Verify the complete integration#

  1. Open your actual website and use its browser developer tools. Confirm guidly-widget.js loads successfully.
  2. Find GET /api/widget-settings. Its X-Guidly-Key header should identify the intended workspace, and the response should contain your saved settings.
  3. Open the launcher and send a question. Confirm POST /api/chat goes to your configured Guidly API host and returns a JSON response.
  4. Try Tutorial mode on a page with a stable control. Complete the action, then check that the guide advances.

Seeing the launcher alone does not prove the key or provider connection works: the widget can render defaults if fetching settings fails. Test a real answer as well.

Keep the script installed#

Saved colors, size, position, title, greeting, Q&A and knowledge load at initialization. After a normal dashboard save, reload the website to apply them. You do not need to regenerate or recopy the snippet. A provider-key replacement or model change is server-side too.

Two changes do require an installation update: staff regenerating the embed key, or moving the widget/API to a different host. Update the corresponding values, then test the request path again. Remove old explicit appearance overrides if you want the dashboard to control those fields.

Serve the widget bundle yourself#

If hosting a widget copy is included in your agreement with Guidly, serve the approved built bundle as a static asset on your website or CDN. Keep data-api-url pointed at the actual Guidly API host; changing where the JavaScript file is hosted does not move the API or database. Confirm distribution and update arrangements before using this approach.

self-hosted.htmlhtml
<script
  async
  src="/guidly-widget.js"
  data-guidly-key="YOUR_EMBED_KEY"
  data-api-url="https://guidly.example"
></script>

Update that static copy when deploying a new widget build. If a CDN or service worker caches the old file, invalidate it through your normal deployment process. Dashboard configuration updates and widget code updates are different: the former change fetched settings; the latter change the JavaScript implementation.

Framework integration and navigation

Guidly is installed through a browser JavaScript snippet, independently of your website's frontend framework or backend language. The integration needs a page that allows the widget script and API requests, with accessible DOM controls for on-page guidance.

Choose the integration point for your stack#

Integration approaches for different website architectures
Website architectureWhere to install Guidly
HTML or server-rendered templatesAdd the standard snippet once in the shared HTML layout used by the pages that need assistance. Your backend language does not change the snippet.
Applications with client-side routingLoad the widget once in the persistent application shell. If that shell unmounts, clean up the widget instance and its script before mounting another one.
CMS and website buildersUse an approved custom-script or shared-template feature, if available. Check that the platform permits the script, API connections, and access to the page controls you want to guide.

Start with the standard installation snippet. React and Next.js below are examples of two integration patterns, rather than an exclusive list of supported stacks. Choose one installation method and verify it on your actual website, including its security policy and navigation behavior.

Example: client-rendered React#

This component owns one widget instance. Its cleanup removes both the mounted widget and its script, which matters when the root is unmounted or development Strict Mode runs an extra setup/cleanup cycle. Render it once in your application shell. Do not also include the HTML snippet.

GuidlyWidget.jsxjsx
import { useEffect } from 'react';

// Mount once near the root of your client-rendered app.
export function GuidlyWidget() {
  useEffect(() => {
    const id = 'guidly-customer-widget';
    if (document.getElementById(id)) return;

    const script = document.createElement('script');
    script.id = id;
    script.async = true;
    script.src = 'https://guidly.example/guidly-widget.js';
    script.dataset.guidlyKey = 'YOUR_EMBED_KEY';
    script.dataset.apiUrl = 'https://guidly.example';
    script.dataset.guidlyEmbed = 'customer-widget';
    document.body.appendChild(script);

    return () => {
      window.dispatchEvent(new CustomEvent('guidly:destroy', {
        detail: { embed: 'customer-widget' }
      }));
      script.remove();
    };
  }, []);

  return null;
}

The data-guidly-embed value names this instance for cleanup. It is unrelated to your workspace embed key. Removing a script tag alone does not remove DOM or event listeners that a loaded widget has already created.

Example: Next.js App Router#

In an App Router application, add the script to the persistent root layout with afterInteractive. Keep the rest of your existing layout, metadata, providers, and styles. This is a complete minimal layout example, not a file you must paste over an existing application.

app/layout.tsxtsx
import type { ReactNode } from 'react';
import Script from 'next/script';

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          id="guidly-customer-widget"
          strategy="afterInteractive"
          src="https://guidly.example/guidly-widget.js"
          data-guidly-key="YOUR_EMBED_KEY"
          data-api-url="https://guidly.example"
        />
      </body>
    </html>
  );
}

The host layout does not need to become a client component just to use next/script. If you use a different framework or router, put the standard script in that framework's persistent HTML shell, or give a client-side loader the same mount/cleanup behavior as the React example.

Single-page navigation and dynamic interfaces#

Guidly gathers page context when a question is sent, so subsequent questions can use the currently mounted route. It does not need a full document reload for every client-side route change. Keep the widget mounted once across those changes.

A generated guide resolves selectors as its steps run. It is not a general route orchestrator: if the next control has not mounted after a navigation, the step can be marked missing. Prefer small tasks that stay within a rendered workflow, and re-ask from the new page when necessary.

How the widget works

From page load to answer#

  1. The browser loads the script and reads supported configuration overrides.
  2. The widget requests saved public settings, merges configuration, and mounts its UI.
  3. A visitor sends a question. The widget collects the current page context and sends a JSON chat request.
  4. The server resolves the workspace, model, provider key, and available monthly allowance. It combines the question, page context, Q&A and knowledge for inference.
  5. The widget displays the returned message. In Tutorial mode, a returned flow can close chat and start highlighting its steps.
  6. If reporting is enabled and supported by the plan, feedback and guide events update that request's analytics record.

The current client reads a complete JSON response; it does not stream partial model tokens into the panel. The standard chat request contains the current message rather than the entire visible conversation history.

What page context contains#

Browser page-context collection
DataCollected content and bounds
Page identityCurrent URL, document title, language and meta description.
Visible textUp to 12,000 characters from the first main / role=main / article match, otherwise the body.
HeadingsUp to 40 h1–h4 text labels.
LandmarksUp to 24 visible region previews, with tag/role and short text.
LinksUp to 40 visible links in the snapshot; the current server prompt uses up to 25.
ControlsUp to 100 eligible interactive elements, with tag, text/label and a generated CSS selector.

This is DOM and text context, not a screenshot. Input values are not deliberately serialized by the control collector, but visible text, URLs, labels and link destinations can still contain application data. Review the content on pages where you install the assistant. See data flow and privacy for the distinction between inference and analytics storage.

Visitor interaction#

The launcher opens chat. Enter sends a question, and the send button does the same. Command/Ctrl + / toggles chat when a guide is not active. Escape closes chat, or ends an active guide. During a guide, use its controls rather than expecting the launcher to reopen the panel.

On supported browsers, the microphone control uses browser speech recognition to help enter text. The browser's speech service may process audio under its own terms. Availability depends on browser support and the host page's microphone permissions; visitors can use text input without enabling it.

Messages are held in the current widget UI; reinitializing the widget starts a fresh instance. The launcher's dragged corner can persist locally, but that is separate from chat history and from the in-memory analytics session.

Styles, accessibility, and host constraints#

The widget uses standard buttons and inputs, accessible labels, a namespaced stylesheet, and fixed-position overlays. It runs in the host document rather than an isolated iframe. Host CSS, unusual stacking contexts, browser top-layer elements and restrictive security policies can still affect the result.

The widget respects reduced-motion preferences for decorative motion. That is one part of accessibility, not a claim that every host integration is compliant. Test keyboard access, focus visibility, text contrast and zoom on the pages your users visit.

A strict Content Security Policy must account for the external script, API connections, and dynamically inserted styles. There is no customer configuration option for attaching a CSP nonce to the injected stylesheet in this version. Test your actual policy rather than assuming that an allowed script automatically permits every style or request it needs.

Build pages that are easy to guide

Guidly generates guidance from the question, your product content, and the controls present on the page. A useful tutorial depends on both accurate instructions and a page the assistant can identify reliably. You do not have to record a tour for every question.

A complete target and guide example#

Suppose a reporting page offers a CSV export. Give the real button a clear visible name and a stable identifier. Your application still owns the click handler, permissions, validation, and download.

reports.htmlhtml
<main>
  <h1>Revenue reports</h1>
  <p>Download the data for the reporting period you selected.</p>
  <button
    type="button"
    data-guidly-id="export-revenue"
    aria-label="Export revenue report as CSV"
  >
    Export CSV
  </button>
</main>

In Tutorial mode, the chat response can contain a flow like this. It is an example of the response format, not a promise that the model will produce identical wording. Question mode can answer without a flow, and Tutorial mode can also return text when a suitable guide cannot be generated.

example-response.jsonjson
{
  "message": "Choose Export CSV to download this reporting period.",
  "flow": {
    "id": "export-revenue",
    "name": "Export a revenue report",
    "triggers": [],
    "steps": [
      {
        "id": "export",
        "selector": "[data-guidly-id=\"export-revenue\"]",
        "title": "Export your report",
        "description": "Click Export CSV to download the selected revenue data.",
        "action": "click"
      }
    ]
  }
}

A flow has an id, name, triggers array, and ordered steps. Each step needs an id, CSS selector, title, and description. Optional action and nextStepTrigger values influence interaction handling; optional valueMin/valueMax bounds apply to numeric controls. For generated chat guides, the selectors identify the current page's controls; the triggers array is not a public customer event subscription mechanism.

The highlighter finds the button using the selector, scrolls it into view, dims the surrounding page, and places a step card near the control. The visitor clicks the actual button. Guidly does not perform the export or bypass your application's authorization.

Choose stable, meaningful controls#

The current collector prefers an element ID, then data-guidly-id, then data-testid, then an aria-label, then an input name. It falls back to classes or a positional selector when stronger identifiers are unavailable. Prefer unique, predictable IDs or data attributes for important actions.

  • Use real buttons, links, labels, inputs, and select elements with useful names. An unlabeled icon communicates less than “Export CSV.”
  • Keep identifiers stable across releases, languages, responsive layouts, and routine data changes. Avoid putting customer IDs or secrets inside them.
  • Use an identifier only once per document. A selector that matches several elements can highlight the first match instead of the intended control.
  • Keep related instructions in your knowledge base current. A stable button cannot correct an outdated product rule.

How a step advances#

Guide progression in the current widget
Control or stepWhat advances the guide
Button or linkThe visitor clicks the highlighted control. A click is an interaction signal, not confirmation that a server operation succeeded.
Text fieldA non-empty, valid value followed by change or blur; Enter can advance an input. For a textarea, use Command/Ctrl + Enter.
Select or rangeA selection or input/change interaction. Range steps with both numeric bounds must meet that band.
Manual stepThe visitor chooses Next in the guide card.
Unavailable targetThe step is treated as missing and the guide attempts to continue. This is useful evidence to investigate in reporting.

The guide card shows the current step and total, the instruction, and controls to stop or skip where applicable. Skipping moves past a step without completing its action. Stopping ends the guide. Completing the normal flow returns to chat; the dashboard setup assistant also restores its task suggestions.

The shared flow shape includes action and nextStepTrigger fields. Do not assume that every value in a TypeScript type implements an automatic browser behavior: the current runtime does not provide a general timed auto-advance or hover-completion mechanism. Use the supported interaction paths above when evaluating a workflow.

Test a real workflow#

  1. Start from the same page, role, and UI state as your visitor. Open any panel required to expose the controls.
  2. Ask a concrete question such as “How do I export this report?” rather than “Show me everything.”
  3. Check that the highlighted element and instruction agree. Use your browser console to test a selector with document.querySelector when debugging.
  4. Perform each action and confirm that your own application finishes it successfully. Repeat with keyboard navigation and a narrow viewport.
  5. Try a permission-restricted account and an empty-data state. Improve your product content or DOM labels where the assistant lacks the necessary context.

A guide does not wait indefinitely for a control that will appear after an asynchronous transition. A route change, virtualized list, closed dialog, iframe, or shadow root may make the next target unavailable. Prefer short workflows with visible controls, and use confirmed outcomes when you need to measure the actual business result.

Configuration reference

Use the dashboard for ordinary customization. Script attributes and the optional window.GUIDLY_CONFIG object are for integrations that deliberately need an override. Set the global object before loading the script; changing it afterwards does not rebuild an existing widget.

Configuration precedence#

For supported appearance fields, the widget uses an explicit script attribute first, then the matching global value, then saved workspace settings, then its built-in default. This is why a hardcoded data-color or data-position can hide changes made in Customize.

before-widget.jsjavascript
// Optional overrides: set BEFORE loading the widget script.
// These values override the matching dashboard settings.
window.GUIDLY_CONFIG = {
  primaryColor: '#0f766e',
  guideAccentColor: '#2563eb',
  widgetTitle: 'AI product help',
  greeting: "I'm an AI assistant. Ask a question or choose a task. Check important answers before acting.",
  position: 'bottom-right',
  analytics: false
};

Supported customer script attributes#

Customer widget script attributes
AttributePurpose
srcBuilt widget JavaScript URL. Use the URL in the generated snippet, or your own deployed copy.
data-guidly-keyPublic workspace embed key. Required for the normal customer integration; never use a provider secret.
data-api-urlGuidly API base URL. Copy it from the generated snippet rather than inferring it from your website.
data-colorPrimary widget color, for example #0f766e. Overrides the saved primary color.
data-guide-accentHighlight/guide accent color. Separate from the primary widget color.
data-positionbottom-right, bottom-left, top-right, or top-left.
data-widget-titleChat header title override.
data-greetingInitial greeting override.
data-question-onlyRestricts the widget to text answers without on-page tutorials.
data-tutorial-disabledDisables Tutorial mode in the normal chat interface.
data-guidly-embedOptional instance label for scoped cleanup with guidly:destroy.

For the two boolean mode attributes, an empty attribute, true, 1, or yes enables the option; false, 0, or no disables it. Use explicit true/false values for clarity. Reserved marketing, demo, and dashboard attributes select internal transports and are not a replacement for your client embed key.

Supported global settings#

Global configuration fields used by customer initialization
FieldMeaning
apiKey / apiUrlFallbacks for the script embed key and API URL.
primaryColor / guideAccentColorColor overrides corresponding to data-color and data-guide-accent.
widgetTitle / greeting / positionText and placement overrides corresponding to the script attributes.
questionOnly / tutorialDisabledBoolean mode restrictions when the corresponding script attribute is absent.
analyticsWhether to collect detailed chat analytics. Defaults to enabled in the normal tenant widget; set false before load to opt out.
analyticsAudienceOptional coarse audience label for Scale reporting.

Launcher size, preset Q&A, and knowledge are managed through workspace settings. The current script initializer does not consume a global launcherSize or faq override, and there is no documented data attribute for them. Prefer the supported settings instead of relying on internal constructor types.

Browser events and consent

The customer widget has a small browser-event surface. Events use window and CustomEvent. Internal events used by the marketing demo and dashboard are not a general customer SDK.

Set analytics: false before loading the widget when detailed reporting should start disabled. To update a running widget, dispatch guidly:analytics-consent with detail.enabled set to a boolean. Disabling it clears remembered reporting receipts, skips queued jobs that have not started, and disables detailed reporting on subsequent chat requests. Requests already sent may finish; the setting does not delete previously collected records.

analytics-consent.jsjavascript
// Initial preference: set this BEFORE loading the widget.
window.GUIDLY_CONFIG = {
  ...window.GUIDLY_CONFIG,
  analytics: false
};

// Call from your consent UI after the widget has initialized.
function setGuidlyAnalyticsConsent(enabled) {
  // Keep the preference available for a later widget initialization.
  window.GUIDLY_CONFIG = {
    ...window.GUIDLY_CONFIG,
    analytics: enabled
  };
  window.dispatchEvent(new CustomEvent('guidly:analytics-consent', {
    detail: { enabled }
  }));
}

The change event is received only after widget initialization has installed its listener. A script load event is not proof that the asynchronous settings request has completed. There is currently no general customer “widget ready” event. For the simplest initial opt-in integration, set the desired global preference before mounting the widget, or defer mounting until your consent UI has a decision.

This switch controls detailed reports. It does not stop the chat request needed to answer a question, provider processing, or monthly usage accounting. If your application must prevent all assistant requests before consent, defer loading the widget itself.

Where consent is required, keep the relevant collection disabled until the visitor makes an affirmative choice and provide a way to withdraw it. The widget's reporting setting is a technical control; choosing a lawful basis and meeting notice requirements need a deployment-specific assessment. See deployment privacy requirements.

Group requests by audience#

On Scale, set an audience label before initialization to compare broad groups such as “Paid customers” and “Trial users.” Use up to 40 characters: start with an ASCII letter and continue with letters, spaces, hyphens, or underscores. Avoid names, email addresses, account IDs, or anything intended to identify a person.

audience.jsjavascript
// Set before loading the widget. Scale reports group requests by this label.
window.GUIDLY_CONFIG = {
  ...window.GUIDLY_CONFIG,
  analyticsAudience: 'Paid customers'
};

Report a confirmed task outcome#

A completed guide shows that the visitor progressed through its steps. To measure whether a download, purchase, or another application task actually succeeded, connect your own success/failure signal. This reporting capability requires Scale.

task-outcomes.jsjavascript
// Register before loading the widget.
window.addEventListener('guidly:answer', event => {
  const requestId = event.detail.requestId;
  // Your application must associate this ID with the relevant task attempt.
  // Example: pendingExport.guidlyRequestId = requestId;
});

// Call only after your own application knows the result of THAT task attempt.
function recordExportOutcome(requestId, success) {
  window.dispatchEvent(new CustomEvent('guidly:task-outcome', {
    detail: { requestId, success }
  }));
}

The guidly:answer event supplies a requestId only when the response includes a reporting receipt and tenant analytics is enabled. It is not fired for every possible answer, including Starter responses without detailed reporting or the public marketing transport. Register the listener before loading the widget, and handle the absence of a receipt.

Your application must associate that request ID with the relevant task attempt. Do not report every later action against the most recent unrelated question, and do not emit success merely because a button was clicked. Only dispatch guidly:task-outcome after your application knows the result.

Customer browser event reference
EventDirection and payload
guidly:answerListen on window. detail.requestId identifies an answer with an analytics receipt. The receipt token remains inside the widget.
guidly:task-outcomeDispatch on window. detail: { requestId: string, success: boolean }. Requires a receipt remembered by the running widget; Scale records outcomes.
guidly:analytics-consentDispatch on window. detail: { enabled: boolean }. Changes detailed analytics for the running instance.
guidly:destroyDispatch on window. detail: { embed: string } limits cleanup to the instance with that data-guidly-embed value. Without an embed value, listeners destroy their instances.

Receipts expire after 24 hours, the client keeps only a bounded recent set, and reinitializing the widget loses its in-memory receipts. These events are designed for the current interaction, not delayed server-side conversion imports. There is no public window.Guidly.open(), generic startTour(), or customer tour registry in this version.

HTTP API reference

The widget handles these endpoints for a standard installation. This reference is useful for inspecting traffic, diagnosing integrations, or building a custom client. Use HTTPS and the same Guidly API base URL as the generated snippet. Examples use placeholders and make no real provider requests.

Authentication and trust boundaries#

GET /api/widget-settings and POST /api/chat use X-Guidly-Key with the public workspace embed key. The server resolves the workspace and its encrypted provider secret. Do not send an Anthropic or OpenAI secret from a browser, and do not put one in an embed snippet.

An embed key identifies an active workspace; it is visible in the installed page. Treat abuse controls and your host's access policy as separate concerns. A client embed key does not grant access to dashboard management routes, which require a signed-in authorized session. The normal cross-origin widget requests do not require credentialed cookies.

GET /api/widget-settings#

settings.shbash
curl 'https://guidly.example/api/widget-settings' \
  -H 'X-Guidly-Key: YOUR_EMBED_KEY'

A successful response includes public widget configuration such as widgetTitle, greeting, primaryColor, guideAccentColor, position, launcherSize, faq, and knowledgeBase. It is fetched without caching at initialization. Do not place secrets in Q&A or knowledge: those settings are available to a holder of the public embed key.

A missing key returns 401. An invalid key or inactive workspace returns 403. A visible default launcher is not evidence that this endpoint succeeded.

POST /api/chat#

Send application/json with message and pageContext. assistMode selects question or tutorial. pageContext needs a URL and title; provide the real current DOM context for useful guidance. The server selects the workspace's saved model and provider credentials, not an arbitrary model supplied by the caller.

chat.shbash
curl 'https://guidly.example/api/chat' \
  -H 'Content-Type: application/json' \
  -H 'X-Guidly-Key: YOUR_EMBED_KEY' \
  --data '{
  "message": "How do I export a revenue report?",
  "assistMode": "tutorial",
  "pageContext": {
    "url": "https://app.example/reports",
    "title": "Revenue reports",
    "language": "en",
    "contentTextSample": "Download the data for the reporting period you selected.",
    "headings": [
      "Revenue reports"
    ],
    "landmarks": [],
    "links": [],
    "elements": [
      {
        "tag": "button",
        "text": "Export CSV",
        "selector": "[data-guidly-id=\"export-revenue\"]",
        "isInteractive": true
      }
    ]
  },
  "analytics": {
    "enabled": false
  }
}'

The message must be non-empty and no longer than 8,000 characters. The standard widget supplies the other context fields automatically. A custom client is responsible for gathering safe, accurate context and implementing any highlighting UI.

Chat request fields
FieldShape and behavior
messageRequired string: the current question. No prior-conversation array is consumed by this endpoint.
assistModeOptional question or tutorial; question is the default.
pageContext.url / titleRequired strings identifying the current page.
pageContext.language / metaDescriptionOptional language and page description strings.
pageContext.contentTextSample / headingsPage text as a string and heading labels as an array of strings. Missing values normalize to empty text/arrays.
pageContext.landmarksArray of { tag, role?, textPreview } describing regions.
pageContext.linksArray of { text, href } describing useful links.
pageContext.elementsArray of { tag, text, selector, isInteractive } describing targetable controls.
analyticsOptional { enabled, session, audience, device }. Use a temporary UUID session such as crypto.randomUUID(), a coarse audience label, and mobile/tablet/desktop when supplying these fields.

The JSON response contains message, optionally flow, and optionally analytics with requestId and token. A text answer without flow is valid. The example flow shows the guide structure. Set analytics.enabled to false when a custom request should omit detailed reporting; it still uses the workspace's question allowance.

Chat endpoint responses
Status / codeMeaning and next action
400Malformed JSON, empty/overlong message, or invalid required page context. Check the request shape.
401No X-Guidly-Key. Copy the workspace embed snippet.
403Workspace is inactive or the embed key is invalid. Confirm the key and workspace status.
503 · ai_not_configuredThe chosen model has no saved provider key. Complete Integrations.
503 · ai_authentication_failedThe upstream provider rejected its stored credentials. Replace the provider key.
503 · ai_model_unavailableThe provider could not use the configured model. Check model access and selection.
429 · monthly_quota_reachedThe workspace reached its monthly question allowance. Check usage and plan.
429 · ai_rate_limitedThe provider throttled the request or its account limits. Check that provider account before retrying.
500Unexpected server/provider failure. Inspect server logs without exposing secrets to users.

POST /api/chat/events#

The standard widget submits feedback, guide progression, and outcome events using a signed receipt returned by chat. This endpoint authenticates the receipt in its JSON body rather than treating an embed key as permission to modify arbitrary analytics records.

Each body needs token and an accepted event type with the appropriate fields. Prefer the standard widget and the documented browser outcome event over creating raw analytics requests. Receipts are time-limited and the workspace's current plan and status are checked again.

Receipt-authenticated reporting event bodies
typeAdditional fields and meaning
feedbackhelpful: boolean. One accepted rating per non-error answer.
startMarks the recorded guide as started. Requires a guide on the original request.
stepstep: zero-based integer index; result: shown, completed, skipped, or missing. The index must be within the recorded guide.
endstep: integer from zero through the guide length. Indicates where it ended; the server derives completion from previously recorded step results.
outcomesuccess: boolean. Scale only; one accepted outcome per non-error answer.

The server makes repeated submissions idempotent for the same rating, outcome, and recorded step result. A 204 is an acceptance response, not proof that a duplicate overwrote an earlier value. The standard client queues events in order so a guide end does not overtake its step results.

The endpoint accepts application/json bodies up to 2,048 bytes. It returns 204 when accepted; 400 for invalid fields; 403 for an invalid/expired receipt or disallowed workspace/plan; 404 when the corresponding report record is unavailable; 413 for an oversized body; 415 for the wrong content type; or 503 if recording fails.

Measure usage and improve answers

Open Analytics for your workspace. Start with three questions: is the AI connection working, what do visitors need help with, and where do answers or guides fail? Reporting is evidence for improving product content and interface design; a large request count by itself is not a measure of success.

What each plan reports#

Reporting by plan
PlanAvailable information
StarterMonthly question usage and operational connection health. Detailed chat reporting is not included.
GrowthUsage over time, common questions, helpful ratings, guide engagement, and items needing attention.
ScaleGrowth reporting plus deeper guide/step analysis, confirmed task outcomes, pages and audience groups, AI performance, period comparisons, CSV export, and optional email summaries/alerts.

Detailed reports require supported-plan requests with collection enabled. Upgrading does not reconstruct events that were never collected. The monthly allowance remains available even if you turn detailed analytics off.

The report refreshes periodically while open; use Refresh when checking a new test request. An “answered” status means a successful response without the model's unanswered marker, not a verified correct answer. Combine status with ratings, guide behavior, and your own task testing.

Read Usage over time#

Choose the last 7 or 30 days. Dates are UTC calendar days, and today is a partial day. The chart includes zero-activity days so the shape reflects quiet periods as well as busy ones.

  • Requests shows answers, unanswered requests, and errors so you can distinguish increased demand from connection problems.
  • Guides compares starts and completions. A completion belongs to the original request's reporting day even if the interaction finished later.
  • Sessions shows temporary widget sessions with requests, rather than a count of known people.

Select a day in the chart or use the date selector and previous/next controls to inspect its numbers. The chart supports Left/Right arrow keys and Home/End for keyboard navigation. Use View all daily numbers when you need an exact date-by-date table.

The daily average divides requests by every calendar day in the selected range, including quiet days. Active days counts days with requests; the busiest day is the day with the most requests. A range with no requests has no busiest day. Avoid comparing a partial today directly with a full previous day.

Metric definitions and denominators#

Analytics definitions
MetricMeaning and interpretation
RequestsRecorded chat attempts in the reporting range. Some failures are included; this is not identical to billable provider usage or the monthly question counter.
Answers / unanswered / errorsSuccessful answer responses, responses classified as unanswered, and failed attempts. Investigate the latter two before assuming that higher volume means useful help.
SessionsTemporary IDs created by the widget, not authenticated people. Reinitializing can create another session; daily counts do not add up to unique people for a month.
Helpful ratePositive ratings divided by positive plus negative ratings. Unrated answers are unknown, not positive.
Guide startsA returned guide actually began in the client. A text-only tutorial response is not a guide start.
Guide completionThe visitor completed the tracked flow without skipped or missing steps. This is interaction completion, not a confirmed business outcome.
Skipped / stopped / brokenA visitor skipped steps, ended the guide, or a guide encountered unavailable controls. These are different reasons to review a task.
Confirmed / unsuccessful outcomeAn application-supplied success or failure signal associated with a specific answer. No signal means unknown.

Common questions and Needs attention#

Common questions groups similar task labels, reusing configured Q&A wording when it matches closely. These are useful topic summaries, not a searchable transcript of every conversation. Question samples are shortened and receive basic masking; they should not be treated as guaranteed anonymous text.

Needs attention brings together unanswered questions, negative ratings, AI errors, and guide problems. Diagnose the type of problem before editing content:

  1. For missing facts, add a direct, current answer in Q&A or knowledge.
  2. For an incorrect UI instruction, check the current page labels and target selectors.
  3. For missing controls, reproduce the page state, responsive layout, permissions, and navigation timing.
  4. For AI failures, check provider credentials, model access, credits, and rate limits in Integrations and the provider account.
  5. Retest the task, then compare new requests over a meaningful period. Historical records are not rewritten when you fix content.

Use the deeper Scale reports#

Guides & outcomes helps identify task and step drop-offs. Look at which step was shown, completed, skipped, missing, or stopped. Compare these patterns with application-confirmed outcomes before redesigning a workflow.

Pages & audience groups activity by sanitized page paths, coarse audience labels, and device category. It is not a user identity system. Set an optional audience label before loading the widget if you need a meaningful segment.

AI performance compares observed models, latency, tokens, and estimated cost. Estimates depend on available usage data and configured rates; your provider invoice is the billing authority. Models serving different tasks or page contexts are not a controlled A/B test.

Period comparisons use the preceding equal-length window. A rising percentage from a tiny sample is weak evidence. Alerts use minimum activity thresholds and are signals to investigate, not automatic judgments about your product. Export CSV to examine or share the underlying summaries; it is not a full chat-transcript export.

Email summaries and alerts#

Scale workspace owners can opt in to weekly summaries and analytics alerts in Analytics. These emails go to the configured workspace owner. Dashboard reports work without email delivery being configured.

The service operator must configure Gmail delivery, CRON_SECRET, and an external scheduler. Weekly processing is eligible on Monday after 08:00 UTC; alerts are limited by the daily job rules and minimum sample thresholds. Delivery timing depends on successful scheduler runs. “Configured” indicates that required environment values are present, not that an external schedule has been installed or a message has reached the inbox.

If email is missing, check opt-in, the owner address, the scheduler response, and sender delivery status. Operators should follow the scheduler setup and monitor actual sends.

Data flow, privacy, and security

Understand three separate data paths: what the widget sends for inference, what Guidly retains for reports, and what the browser stores locally. They have different purposes and lifetimes. Turning off one does not necessarily turn off the others.

Data used to answer a question#

When a visitor sends a question, the widget sends the current question and DOM context to your Guidly API. The server combines those with the workspace's configured Q&A and knowledge and calls the selected AI provider using its saved key. This context can include page text, titles, labels, URLs, and link destinations.

The control collector does not deliberately serialize input values as a field. However, page text, headings, labels, metadata, URLs and links may contain personal or confidential information. CSS visibility is not a data-redaction boundary for every part of the snapshot. Review the actual request payload using sample data, avoid URLs containing secrets, and limit installation to suitable pages.

Data stored for reports#

Detailed analytics stores bounded request metadata: shortened/masked question samples, normalized task labels, sanitized page paths, temporary session identifiers, coarse device/audience labels, result status, feedback, guide/step events, and available model usage/timing. It does not store the full answer, full chat transcript, full DOM snapshot, IP address, or provider secret in those reporting records.

These report records are configured to expire after 90 days. Expired records are excluded from report queries while database cleanup runs. Provider processing, operational logs, backups and other service records have separate retention arrangements; this setting does not establish a universal deletion deadline for all copies of data.

Question masking reduces accidental identifiers but is not guaranteed anonymization. Page-label sanitization removes query strings and fragments and normalizes many identifier-like path segments for reporting. The original current URL can still be part of inference context.

Browser state and consent#

The launcher corner preference uses local storage scoped to the API URL and embed key. The analytics session ID and reporting receipts are in memory for the widget instance. Reinitializing the widget does not restore the previous chat transcript or receipt map.

Disabling detailed analytics does not disable launcher preference storage, widget loading requests, chat processing, or monthly usage accounting. Guidly's public showcase also uses IP-based or visitor-based quota records separately from customer performance reports; see the Privacy Policy. Signed-out use should not be understood as anonymous processing.

Guidly's own landing page offers cookie preferences through its footer, while demo/docs surfaces keep their own preference entry points. Your customer website needs its own appropriate disclosure and preference controls. The customer widget does not automatically adopt another site's cookie banner decision; wire your decision to the analytics control, or defer mounting when that is your intended policy.

Protect credentials and public content#

  • Store provider secrets only in Integrations. They are encrypted at rest and used server-side.
  • Expect the embed key to be visible in page source and browser requests. It is not a private server credential.
  • Assume Q&A and knowledge are public widget content. Do not store internal secrets or individual account records there.
  • Regenerating an embed key invalidates the old integration; update all installations. Replacing a provider secret does not require a new embed snippet.
  • For operators, protect database access, authentication secrets, encryption keys, scheduler secrets, logs, and backups independently.

Prepare a customer deployment#

Before a business integration processes personal data on a customer's behalf, contact Guidly to agree the applicable data-processing terms. Confirm the parties' roles, the AI and infrastructure providers, processing locations, transfer safeguards, retention, and arrangements for data-subject requests. The EDPB guidance on controllers and processors explains the relevant responsibilities.

Identify AI-generated assistance clearly at the first interaction, using the title, greeting, or another visible disclosure in the actual interface. Review applicable requirements, including the EU AI Act's transparency provisions. Editing a greeting alone is not a complete assessment of an AI system's obligations.

Where optional collection requires consent, configure it to remain disabled until an affirmative choice and provide an accessible withdrawal control. Assess chat processing and browser storage separately from performance reporting. See the EDPB guidance on lawful processing and consent. Installation and configuration steps do not, by themselves, certify legal or accessibility compliance.

Run and operate Guidly

This section is for authorized developers and operators with access to the Guidly source and deployment environment. Hosting and distribution rights depend on your agreement with Guidly. Installing the customer script does not require running your own Guidly server. Workspace owners can continue with the installation and troubleshooting guides.

Project structure#

Repository packages
PathResponsibility
apps/dashboardNext.js application: marketing/docs/demo, authentication, client dashboard, APIs, provider calls, MongoDB persistence, and email jobs.
apps/widgetTypeScript browser widget, chat UI, page-context collection, highlights, and analytics transport. Built as a standalone JavaScript bundle.
packages/sharedShared configuration, page-context, guide, and analytics types. Types alone do not imply that every field is exposed by the public loader.
apps/dashboard/public/guidly-widget.jsThe deployed widget asset served by the dashboard. Generated from the widget build.

Local development#

  1. Install Bun and use a Node.js environment compatible with the repository's Next.js toolchain. Use the repository lockfile and package manifests for dependency versions.
  2. Copy apps/dashboard/.env.example to apps/dashboard/.env.local. Fill in the required values below. Keep the local file out of version control.
  3. Run the commands below. Replace the seed command's example email and password with the first staff account's credentials. It reads arguments rather than prompting. Use a strong, unique password and handle the command's credentials according to your shell-history policy.
  4. Open the dashboard at http://localhost:3000, sign in as staff, create a client workspace, and complete the client quickstart with real provider credentials.
terminalbash
# Run from the repository root after configuring .env.local.
bun install
bun run seed-admin -- 'you@example.com' 'REPLACE_WITH_A_STRONG_PASSWORD' 'Admin'
bun run dev:dashboard

The dashboard dev/build commands build and copy the widget before starting Next.js. If you edit widget code while the dashboard is already running, run bun run sync-widget from the repository root and reload the host page. The separate bun run dev:widget command is available for widget development; verify the asset actually used by your host page.

Environment variables#

Deployment environment reference
VariablePurpose
MONGODB_URIRequired server-side database connection. Allow the deployment network to reach the database.
MONGODB_DB_NAMEOptional database name; defaults to guidly. Use a separate development database.
NEXTAUTH_SECRETRequired high-entropy authentication secret. Keep consistent across server instances.
NEXTAUTH_URLCanonical application URL; localhost:3000 for local development, HTTPS origin in production.
ENCRYPTION_KEYRequired 32-byte encryption key encoded as 64 hex characters. Generate a random key; do not use the example zeros.
NEXT_PUBLIC_CONTACT_EMAILPublic contact address shown in the site and legal pages. This is intentionally public.
GMAIL_USER / GMAIL_APP_PASSWORDOptional SMTP sender and app password for contact forms and analytics emails. Use an app password, not the account login password.
CONTACT_INBOX_EMAIL / CONTACT_FROM_NAMEOptional destination and display name for contact-form messages.
CRON_SECRETRequired only for authenticated analytics scheduling. Use a separate random secret.
CAL_API_KEY / CAL_EVENT_TYPE_IDOptional server-side booking integration. Leaving either empty hides booking.
GUIDLY_ANTHROPIC_MODELOptional marketing/demo model override; not a tenant-wide inference fallback.
MARKETING_GUEST_QUOTA_SALT / DEMO_EDITOR_QUOTA_SALTOptional dedicated salts for the public showcase quota hashes.

Generate an encryption key with node -e "console.log(require('crypto').randomBytes(32).toString('hex'))". Keep it in your secret manager and backup policy. Replacing it without migrating encrypted records can make saved provider credentials unreadable. Never prefix server secrets with NEXT_PUBLIC_.

Tenant Anthropic/OpenAI credentials are configured per workspace in the dashboard, not through a shared server-wide fallback. Staff configure the public marketing/demo provider separately in Chatbot settings.

Production deployment checklist#

  1. Set production environment values, HTTPS, database access, and the canonical authentication URL. Keep development and production credentials separate.
  2. Build the dashboard with its package build script and start the built Next.js application. Confirm the generated public widget bundle is included in the deployment.
  3. Verify login, client scope, workspace settings persistence, and encrypted-key reads after a server restart. A successful static page load does not test these dependencies.
  4. Copy a newly generated snippet onto a real host page. Verify settings, an answer, and a tutorial across origins using production URLs.
  5. Check host CSP, cache/service-worker behavior, mobile layout, and keyboard access. Update any separately hosted widget copy when releasing widget changes.
  6. Enable only the optional booking, contact, and email features you have configured and tested. Monitor failures in server logs without logging raw secrets or unnecessary page context.
production-terminalbash
# From the repository root, with production environment values set.
bun run --filter @guidly/dashboard build
bun run --filter @guidly/dashboard start

Configure the Scale analytics scheduler#

  1. Set GMAIL_USER, GMAIL_APP_PASSWORD, and a strong CRON_SECRET on the server.
  2. Configure an external scheduler to call GET /api/cron/analytics every 15 minutes with Authorization: Bearer followed by that secret.
  3. Opt a Scale workspace into the desired emails and confirm its owner address.
  4. Test an authenticated call and inspect its JSON result and server logs. Monitor future scheduler calls and actual email delivery.
scheduler-request.shbash
curl 'https://guidly.example/api/cron/analytics' \
  -H 'Authorization: Bearer YOUR_CRON_SECRET'

The endpoint rejects unauthenticated requests. Each run processes a bounded batch of due workspaces; repeated scheduling is necessary. The worker uses claims and delivery records to reduce duplicate sends and checks workspace eligibility again before delivery. SMTP delivery can still be uncertain, so do not promise exactly-once email delivery.

Weekly messages become eligible on Monday after 08:00 UTC. Alerts use daily delivery limits and sample thresholds. If your workspace count or job duration grows, monitor backlog and scheduling frequency rather than treating environment-variable presence as proof of operational readiness.

Troubleshoot an integration

Diagnose the first failing layer: script, settings, chat, then guidance or reporting. Keep the browser Network tab open while reproducing the problem. A screenshot of a black launcher alone cannot show which layer failed.

The launcher does not appear#

  1. Check that the script is present on the current route and its URL returns JavaScript successfully. A 404 or an HTML error page cannot initialize the widget.
  2. Check browser console errors, Content Security Policy reports, ad blockers, and network failures.
  3. Verify that the widget/API URLs are HTTPS on an HTTPS website. Confirm your deployment serves the expected built asset.
  4. Look for a pending settings request. Initialization waits for that request; loading the JavaScript file is only the first stage.
  5. Check for duplicate script installations or a component that immediately unmounts its script. Mount the widget once in the persistent application layout.

Saved customization does not appear#

First click Save in Customize, then reload the installed website. Inspect /api/widget-settings and compare its returned title, color, position, and launcherSize with the intended workspace. If the response belongs to another workspace, fix the embed key rather than repeatedly changing colors.

Diagnose configuration differences
SymptomCheck
Position updates but color stays blackRemove data-color or a global primaryColor override, then reload. Primary color changes the launcher/header/visitor bubbles; assistant bubbles remain neutral.
Guide outline has the wrong colorCheck Guide accent separately from Primary color and remove any data-guide-accent override.
Launcher stays in a dragged cornerThe browser remembers its visitor-selected corner until the configured corner changes. Test in a fresh browser profile or change the saved corner.
Size does not updateSave Button size, reload, and verify launcherSize in settings. Use the dashboard size control rather than an unsupported script attribute or global field.
Local copy works but production looks oldConfirm the production bundle version and CDN/service-worker cache. A separately hosted JavaScript copy must be updated with widget releases.
Client styling does not affect Guidly’s landing chatbotThe public showcase uses its own staff-managed configuration. Test your installed client widget.

The launcher opens but replies fail#

Check the status and response body of POST /api/chat. A key saved in the provider field and a key copied into the script have different jobs.

  • 401 or workspace 403: verify the public embed key and active workspace. A regenerated embed key needs to be replaced on the website.
  • ai_not_configured: store the provider key for the model actually saved, and save the model if you changed it.
  • ai_authentication_failed: replace the provider credential. A provider authentication error does not mean the public embed key is wrong.
  • ai_model_unavailable: check provider model access or select another model supported by your plan.
  • monthly_quota_reached: check the workspace's monthly allowance and plan.
  • ai_rate_limited: inspect provider account limits and credits. A different issue from the Guidly monthly cap.
  • Other server failures: operators should inspect API/database logs and encrypted-key configuration. Avoid posting secrets in a support request.

If the answer is factually weak rather than technically failing, ask it on the relevant page, make the question self-contained, and review Q&A and knowledge. The standard request does not include the entire previous conversation. A knowledge edit will not fix an invalid provider key, and a new key will not correct outdated product facts.

A guide highlights the wrong thing or skips a step#

Reproduce the same viewport, role, route, and open panels. Confirm that the selected element exists at the moment the step runs and that its selector is unique. Prefer a stable ID or data-guidly-id over classes generated by a build tool.

Check whether the control is inside an iframe or shadow root, is virtualized, or appears only after an asynchronous route transition. The standard selector lookup does not cross those boundaries or wait indefinitely. Add meaningful DOM controls, narrow the task, or restart help from the destination page.

If there is a text answer without a spotlight, confirm Tutorial mode is selected and not disabled. Then inspect whether the response contains a usable flow. Guidly can answer without generating one; Question mode intentionally stays in chat.

Analytics is empty or differs from usage#

  1. Confirm the workspace has Growth or Scale and detailed analytics was enabled before the request. Starter includes the allowance counter rather than these reports.
  2. Check that you tested the tenant widget. Signed-out public-demo requests do not create the same client report records.
  3. Check the chosen date range, UTC day, and current workspace, then refresh the report.
  4. For missing feedback or guide progression, inspect /api/chat/events. Browser blocking, expired receipts, reloads, or a plan change can prevent later events.
  5. For outcomes, use Scale, retain the correct request association, and emit the signal after the actual application result. Unreported results remain unknown.

Do not expect Requests to match the monthly counter exactly: failed attempts, collection settings, report retention, and collection eligibility differ. Do not interpret session counts as unique customers or missing ratings as positive feedback.

Before you launch#

  • One script is installed on the intended pages, with the correct public key and API host.
  • The saved model has a working provider credential and a successful real answer.
  • The title, greeting, colors, size, corner, suggestions, and knowledge match your product after reload.
  • Several important tasks work on desktop, mobile, and permission-restricted accounts.
  • Keyboard access, zoom, contrast, host CSS, and CSP have been checked in the actual integration.
  • Public knowledge contains no secrets, and your disclosure/consent choices match how you mount the widget and collect reports.
  • The chat identifies AI-generated assistance clearly, and any required data-processing arrangements and user notices are in place for your deployment.
  • Your team knows who maintains content, reviews Needs attention, rotates provider secrets, and handles failures.

What to include in a support request#

Share the workspace name, affected route, browser/device, approximate time with timezone, reproduction steps, and the failing endpoint's status/error code. Include a sanitized screenshot or selector when targeting is the issue. Exclude provider secrets, passwords, private page content, and full receipt tokens.

Glossary

Common documentation terms
TermDefinition
API base URLThe Guidly server origin used for settings, chat, and events; distinct from the website where the widget is installed.
DOMThe browser’s document structure. Guidly uses its text and elements to understand the page and target controls.
SelectorA CSS expression identifying a target element, such as [data-guidly-id="export-revenue"].
Flow / stepA guide response and one instruction within that guide.
InferenceThe server asking the chosen AI model to generate an answer from the supplied context.
ProviderThe external AI service whose saved API key and model produce the workspace’s replies.
ReceiptA signed, expiring token tying a reporting event to a recorded request. It is not a dashboard credential.
SessionA temporary widget-instance identifier used for reporting, not proof of a unique person.
OutcomeYour application’s report that a particular task succeeded or failed, distinct from finishing guide steps.
UTCThe timezone used for report days, calendar-month allowances, and scheduler eligibility.

Next steps and support

If you are setting up a workspace, follow the quickstart and use the dashboard setup assistant. If you are integrating a website, start with installation, then review guide-friendly controls and data flow.