The Ferndesk SDK is a lightweight JavaScript library that provides programmatic control over the Self-Service Widget. Once embedded, it exposes a global Ferndesk object on window.Ferndesk that allows you to initialize the widget, open articles, trigger searches, and manage visibility, all from your site's JavaScript code.

Getting started

Installation

First, embed the Ferndesk SDK script in your HTML (or copy from the Ferndesk dashboard):

<!-- Step #1. Install the Ferndesk SDK -->
<script>
    !(function (e, t) {
        var n = 'ferndesk-sdk',
            r = e.FERNDESK_SDK_SRC || 'https://static.ferndesk.com/dist/sdk.js',
            c = 'Ferndesk',
            s = t.currentScript;
        function a() {
            if (!t.getElementById(n)) {
                var e = t.createElement('script');
                ((e.id = n),
                    (e.src = r),
                    (e.async = !0),
                    s && s.nonce && ((e.nonce = s.nonce), e.setAttribute('nonce', s.nonce)));
                var c = t.getElementsByTagName('script')[0];
                c.parentNode.insertBefore(e, c);
            }
        }
        if ('function' != typeof e[c]) {
            var i = [],
                o = function () {
                    i.push(arguments);
                };
            ((o.q = i), (e[c] = o));
        }
        'complete' === t.readyState || 'interactive' === t.readyState
            ? a()
            : t.addEventListener('DOMContentLoaded', a);
    })(window, document);
</script>

Initialization

Initialize the widget with your widget ID:

<script>
Ferndesk('init', { widgetId: 'YOUR_WIDGET_ID' })
</script>

Once initialized, the widget appears as a floating button on your page, and all SDK methods become available.

The widgetId parameter is required.

Core methods

Init

Initialize the Ferndesk widget.

Ferndesk('init', { widgetId: 'YOUR_WIDGET_ID', open: true })

Parameters:

  • widgetId (string, required): Your widget ID from the Ferndesk dashboard.

  • open (boolean, optional): If true, the widget opens automatically on page load. Default: false.

Returns: None. Triggers widget initialization.

Console errors:

  • Ferndesk: init requires a widgetId — widgetId parameter is missing.

  • Ferndesk widget failed to load widget configuration — The widget ID is invalid or not found.

Hide

Hide the widget button and disable interaction.

Ferndesk('hide')

Parameters: None.

Returns: None.

Behavior: Hides the widget button and closes any open panels. Users cannot access the widget until show() is called.

Example use case: Hide the widget on pages where help isn't needed:

if (window.location.pathname === '/checkout') {
  Ferndesk('hide');
}

Show

Display the widget button and make it interactive.

Ferndesk('show')

Parameters: None.

Returns: None.

Behavior: Makes the widget button visible. If already visible, no change occurs.

Example use case: Show the widget after a user performs a certain action:

document.getElementById('help-button').addEventListener('click', () => {
  Ferndesk('show');
});

Open

Open the widget help panel programmatically.

Ferndesk('open')

Parameters: None.

Returns: None.

Behavior: Opens the main widget panel without navigating to a specific article. Users see the help center home.

Example use case: Open help when a user clicks a "Get Help" button:

document.getElementById('get-help').addEventListener('click', () => {
  Ferndesk('open');
});

Close

Close the open widget panel.

Ferndesk('close')

Parameters: None.

Returns: None.

Behavior: Closes any open widget panel, sidebar, or modal. The widget button remains visible and clickable.

Destroy

Remove the widget completely and free resources.

Ferndesk('destroy')

Parameters: None.

Returns: None.

Behavior: Removes the widget from the page, clears event listeners, and resets state. To use the widget again, call init() with a new widget ID.

Example use case: Clean up the widget on page unload in single-page apps:

window.addEventListener('beforeunload', () => {
  Ferndesk('destroy');
});

Content navigation methods

OpenArticle

Open a specific article in the widget.

Ferndesk('openArticle', { shortId: 'help-123', presentation: 'widget' })

Parameters:

  • shortId (string, required): The last part of the article's.

  • presentation (string, optional): How to display the article. Options: 'widget' (default), 'sidebar', 'modal', 'inline'.

  • anchor (HTML element, optional): Required for 'inline' presentation. The element to anchor the article near.

Returns: None.

Presentation modes:

  • widget (default): Article opens inside the main help widget.

  • sidebar: Article slides in from the right edge as a side panel.

  • modal: Article opens in a centered full-screen overlay.

  • inline: Article expands near the anchor element (requires anchor parameter).

Example — Open article in modal on button click:

document.getElementById('faq-button').addEventListener('click', () => {
  Ferndesk('openArticle', { shortId: 'faq-pricing', presentation: 'modal' });
});

Example — Open article inline next to an element:

const anchorElement = document.getElementById('billing-info');
Ferndesk('openArticle', {
  shortId: 'billing-faq',
  presentation: 'inline',
  anchor: anchorElement
});

Console errors:

  • Ferndesk: openArticle requires a shortId — shortId is missing.

  • Ferndesk: Inline floating article requires an anchor elementpresentation: 'inline' but no anchor provided.

  • Ferndesk: openArticle ignored because the widget has not been initialisedinit() hasn't been called yet.

OpenCollection

Open a specific collection in the widget.

Ferndesk('openCollection', { shortId: 'getting-started' })

Parameters:

  • shortId (string, required): The collection's short ID from your help center.

Returns: None.

Behavior: Opens the collection inside the widget help panel, displaying all articles in that collection.

Example — Browse troubleshooting articles:

Ferndesk('openCollection', { shortId: 'xFqsqw' });

Populate the widget search and display results.

Ferndesk('search', { query: 'billing issues' })

Parameters:

  • query (string, required): The search query. Must be non-empty.

Returns: None.

Behavior: Opens the widget and displays search results matching the query. If no results match, displays "No results found."

Example — Search when user presses a key combination:

document.addEventListener('keydown', (e) => {
  if (e.key === '?' && e.ctrlKey) {
    Ferndesk('search', { query: 'download videos' });
  }
});

Console errors:

  • Ferndesk: search requires a non-empty query — query parameter is empty or missing.

Data attributes for inline triggers

In addition to SDK methods, you can use HTML data attributes to trigger widget actions without JavaScript:

data-ferndesk-article

Open an article in widget mode when clicked.

<button data-ferndesk-article="help-123">Learn More</button>

Clicking this button opens the article with ID "help-123" in the main widget panel.

data-ferndesk-article-modal

Open an article in modal mode when clicked.

<a href="#" data-ferndesk-article-modal="pricing-faq">View Pricing FAQs</a>

Clicking this link opens the article in a centered modal overlay.

data-ferndesk-article-sidebar

Open an article in sidebar mode when clicked.

<button data-ferndesk-article-sidebar="troubleshooting">Troubleshoot</button>

Clicking opens the article in a slide-in sidebar.

data-ferndesk-article-inline

Open an article in inline mode anchored to the clicked element.

<button id="my-button" data-ferndesk-article-inline="quick-help">Quick Help</button>

Clicking this button opens the article inline near the button. If no anchor is found, the browser console warns and falls back to modal mode.

Error handling and logging

The SDK logs errors and warnings to the browser console (not shown to end-users). Common messages include:

Message

Cause

Solution

Ferndesk: init requires a widgetId

Missing widgetId parameter

Provide your widget ID in the init call

Ferndesk widget failed to load widget configuration

Invalid or expired widget ID

Verify the ID in the dashboard; regenerate if needed

Ferndesk service not found

SDK script didn't load (blocked by ad blocker, CSP, etc.)

Check network requests; whitelist Ferndesk domain in CSP

Ferndesk: search requires a non-empty query

Empty or missing search query

Provide a non-empty string for the query parameter

Ferndesk: Inline floating article requires an anchor element

Using inline presentation without anchor

Provide an HTML element in the anchor parameter

Ferndesk: 'method' ignored because the widget has not been initialised

Called a method before init() completed

Ensure init() is called before other methods (or wait for SDK load)

Ferndesk: unknown command 'method'

Called a non-existent method

Check the method name and spelling against the SDK reference

Content Security Policy (CSP) compliance

If your site uses a strict Content Security Policy, you may need to allowlist the Ferndesk domain:

Example CSP header:

script-src 'self' https://static.ferndesk.com;

If the SDK script is blocked by CSP, the console logs a CSP violation error. Add https://static.ferndesk.com to your script-src directive to allow it.

Performance considerations

The SDK uses asynchronous loading to avoid blocking page rendering. Typical load time is 200-500ms on a standard connection.

  • Async loading: The SDK script loads asynchronously in the background. Your page continues loading while the SDK initializes.

  • Shadow DOM isolation: The widget uses shadow DOM to encapsulate styles and prevent conflicts with your site's CSS.

  • Lazy content loading: Articles and search results load on demand, not all at once.

  • No performance impact: The SDK adds minimal overhead, typically less than 50KB of JavaScript.

Examples

Basic setup

<html>
  <body>
    <!-- Your page content -->
    
    <script src="https://static.ferndesk.com/dist/sdk.js"></script>
    <script>
      Ferndesk('init', { widgetId: 'your-widget-id' });
    </script>
  </body>
</html>

Open article on button click

<button id="help-btn">Get Help</button>

<script>
Ferndesk('init', { widgetId: 'your-widget-id' });

document.getElementById('help-btn').addEventListener('click', () => {
  Ferndesk('openArticle', {
    shortId: 'faq-overview',
    presentation: 'modal'
  });
});
</script>

Search on user input

<input id="search-input" type="text" placeholder="Search help..."/>

<script>
Ferndesk('init', { widgetId: 'your-widget-id' });

document.getElementById('search-input').addEventListener('keypress', (e) => {
  if (e.key === 'Enter') {
    Ferndesk('search', { query: e.target.value });
  }
});
</script>

Context-aware help in a React app

import { useEffect, useState } from 'react';

export default function App() {
  const [currentPage, setCurrentPage] = useState('home');

  useEffect(() => {
    // Initialize SDK
    const script = document.createElement('script');
    script.src = 'https://static.ferndesk.com/dist/sdk.js';
    script.async = true;
    document.body.appendChild(script);

    script.onload = () => {
      window.Ferndesk('init', { widgetId: 'your-widget-id' });
    };
  }, []);

  useEffect(() => {
    // Hide widget on checkout page, show elsewhere
    if (currentPage === 'checkout') {
      window.Ferndesk('hide');
    } else {
      window.Ferndesk('show');
    }
  }, [currentPage]);

  return (
    <div>
      {/* Your page content */}
    </div>
  );
}

What's next

Was this helpful?