---
updatedAt: 2026-07-31T11:52:45.000Z
agentTools:
  projectIndex: https://developers.graphcomment.com/llms.txt
---

# Widget configuration

Every __semio__params option, plus page callbacks, widget events, runtime commands and theming.

Everything the comment widget does is driven by one JavaScript object: `__semio__params`. You already met it in [Getting Started](./getting-started) — this page documents every option it accepts, plus the callbacks your page can define, the events the widget emits, and the commands you can send it at runtime.

## The configuration object at a glance

```javascript
var __semio__params = {
  graphcommentId: "<shortname>",   // required — your site's shortname

  behaviour: {
    uid:                 "article-12345",             // recommended — stable thread ID
    url:                 "https://my.site/article",   // canonical URL (if query strings vary)
    readonly:            false,                       // true = display only, no posting
    sort:                "newest",                    // "newest" | "oldest" | "relevance"
    countPerPage:        10,                          // top-level discussions per page
    inapp:               false,                       // true only inside a mobile WebView
    lifetime:            30,                          // days during which commenting stays open
    publication_date:    "2026-06-02T12:00:00Z",      // article publication date (ISO 8601)
    telemetricTroughCmp: false                        // true to enable CMP-gated telemetry
  },

  statistics: {
    pageTitle: "My article title",   // shown in your back-office statistics
    category:  "Tech"                // page category, for your stats
  },

  integration: {
    fixedHeaderHeight: 60            // px height of your fixed header (scroll offset)
  }
};
```

All three sections are optional — a bare `graphcommentId` is enough to load the widget. Each option is detailed below.

> 📘 Using single sign-on?
> With SSO the widget takes an extra `auth` section and loads through a different script. See [Single Sign-On](./authentication-sso) — everything on this page still applies.

## Which script loads the widget

GraphComment ships two loader scripts, depending on whether you use SSO:

| Setup                       | Script             | Init function                             |
| --------------------------- | ------------------ | ----------------------------------------- |
| Standard widget (no SSO)    | `gc_graphlogin.js` | `__semio__gc_graphlogin(__semio__params)` |
| With SSO (`helpers_sso.js`) | `gc.js`            | `__semio__gc(__semio__params)`            |

Both are served from `https://integration.graphcomment.com/` and both read the same `__semio__params` object. The [Getting Started](./getting-started) snippet uses the standard loader.

## `behaviour` options

| Option                | Type    | Description                                                                                                                                                   |
| --------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `uid`                 | string  | **Recommended.** A stable, unique identifier for the thread (your CMS post ID is ideal). This is what keeps comments attached to their page when URLs change. |
| `url`                 | string  | The canonical URL of the page. Set it explicitly if your page can be reached with varying query strings.                                                      |
| `readonly`            | boolean | `true` renders the thread in display-only mode: visitors can read but not post.                                                                               |
| `sort`                | string  | Sort order: `"newest"`, `"oldest"` or `"relevance"` — note that this is one layer of four, see "Who decides the sort order" below.                            |
| `countPerPage`        | number  | Number of top-level discussions loaded per page.                                                                                                              |
| `inapp`               | boolean | Set to `true` only when the widget runs inside a mobile WebView. See [Mobile (WebView)](./mobile-webview).                                                    |
| `lifetime`            | number  | Number of days, counted from the publication date, during which new comments can be posted.                                                                   |
| `publication_date`    | string  | The article's publication date, ISO 8601 (used with `lifetime`).                                                                                              |
| `telemetricTroughCmp` | boolean | `true` enables telemetry gated by your consent management platform.                                                                                           |

### `uid` and `url`: thread identity

GraphComment automatically strips query-string parameters from the page URL so that one page resolves to one thread. If your page can be reached with extra parameters, don't rely on the URL for identity — set `uid` (and `url` if needed):

```javascript
behaviour: {
  uid: "post-12345",
  url: "https://your-site.com/article.html"
}
```

> ⚠️ `uid` is the setting that matters most
> A stable `uid` makes your threads survive domain migrations, trailing-slash changes and tracking parameters. Set it once, from an identifier you control, and never change it.

Three rules to keep out of trouble:

* **Never give the same `uid` to two different pages.** Their comments would be mixed into a single thread — and that cannot be undone: two threads can't be merged, or un-merged.
* **If your page is itself rendered inside an iframe** (embedded widgets, Google Sites…), the URL the widget sees may be the iframe's, not your page's — `uid` becomes mandatory there.
* **On WordPress, skip all of this**: the [plugin](./wordpress) manages thread identity automatically.

> 📘 Building a SPA?
> To switch threads on internal navigation without a page reload, update `behaviour.uid` and call the init function again — the pattern is shown in [Single Sign-On](./authentication-sso) and works the same without SSO.

### Who decides the sort order

`behaviour.sort` is one layer of four. The widget resolves the sort order in this priority, highest first:

1. **The visitor's own choice** — when someone picks a sort order in the widget, it's remembered in their browser for that page and wins on every return visit.
2. **The logged-in user's saved preference** — a GraphComment account carries a sort preference.
3. **Your `behaviour.sort`** — from the snippet.
4. **Your site's back-office setting** — the site-wide default when none of the above is set.

So `behaviour.sort` sets the order for first-time, anonymous visitors — it does not override a choice the visitor already made. Don't be surprised if a returning visitor sees a different order than the snippet forces.

## `statistics` options

These values feed the statistics you see in your GraphComment back-office. They don't change how the widget renders.

| Option      | Type   | Description                                                  |
| ----------- | ------ | ------------------------------------------------------------ |
| `pageTitle` | string | The article title, as you want it to appear in your stats.   |
| `category`  | string | A free-form category for the page (e.g. `"Tech"`, `"News"`). |

## `integration` options

| Option              | Type   | Description                                                                                                                           |
| ------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `fixedHeaderHeight` | number | Height in px of your site's fixed header. The widget uses it as a scroll offset so anchored scrolling doesn't land under your header. |

## Consent management (TCF v2)

If your site runs a consent management platform implementing IAB TCF v2, the widget integrates with it through the standard `window.__tcfapi` interface: it reads the vendor consent status via `getTCData` and behaves accordingly — consent refused means comments are not loaded, consent pending means the widget waits, consent granted means normal loading.

## Page callbacks

Your page can define two global callbacks. Define them **before** the loader script runs:

```javascript
// Called when a visitor posts a new comment
window.gcOnComment = function (commentData) {
  // e.g. notify your analytics
};

// Called when the widget is ready
window.onGcLoaded = function () {
  // e.g. remove your placeholder/skeleton
};
```

## Widget events (postMessage)

The widget runs in an iframe and reports its lifecycle to the parent page with `postMessage`. The loader script consumes most of these itself (that's how the iframe auto-resizes), but your page can listen too:

| Event            | Emitted when                                                |
| ---------------- | ----------------------------------------------------------- |
| `gc-ready`       | The widget is ready.                                        |
| `gc-loaded`      | The widget is fully loaded.                                 |
| `gc-new-comment` | A new comment was posted (carries the comment data).        |
| `gc-height`      | The widget's height changed (carries the new height in px). |
| `gc-scroll`      | The widget requests a scroll of the parent page.            |
| `gc-reload`      | The widget requests a comments reload.                      |

Messages are JSON payloads whose `name` field carries the event name:

```javascript
window.addEventListener("message", function (ev) {
  var msg;
  try {
    msg = typeof ev.data === "string" ? JSON.parse(ev.data) : ev.data;
  } catch (e) { return; }
  if (msg && msg.name === "gc-new-comment") {
    // react to the new comment
  }
});
```

> 👍 Prefer the callbacks
> For the two common cases — "a comment was posted" and "the widget is ready" — `window.gcOnComment` and `window.onGcLoaded` do the message plumbing for you.

## Runtime commands

The loader script exposes these functions on `window`; they act on the widget immediately — from your own code or straight from the browser console.

| Command                          | Signature             | Effect                                                                                              |
| -------------------------------- | --------------------- | --------------------------------------------------------------------------------------------------- |
| `__semio__gcSetLang`             | `('fr')`              | Switch the widget's UI language.                                                                    |
| `__semio__gcToggleCommentScores` | `()`                  | Show/hide comment scores.                                                                           |
| `__semio__gcLightTheme`          | `(accent?)`           | Switch to the light theme. `accent` is a named preset or a `#rrggbb` hex color.                     |
| `__semio__gcDarkTheme`           | `(palette?, accent?)` | Switch to the dark theme. `palette` is one of `neutral`, `slate`, `deep-blue`, `moonlit`, `carbon`. |

## Light and dark themes

The theme is decided in this order:

1. **Your back-office setting** (Settings → Customization) comes first. If you've forced light or dark there, that wins.
2. When the back-office setting is **auto** (the default), the widget detects the theme from the colors of the page that embeds it.
3. At runtime, you can switch explicitly:

```javascript
// Force the light theme with your brand accent color
__semio__gcLightTheme('#f35b5b');

// Force the dark theme
__semio__gcDarkTheme('slate');
```

Call these at any time after the widget has loaded — for example from your site's own dark-mode toggle, so the comment thread follows your theme switch instantly.

## Advanced options

> ⚠️ Not part of the stable public contract
> The options below exist and work, but they are internal integration options: they may change without notice and are not covered by the documented baseline above. Use them knowingly.

**`behaviour` (advanced):**

| Option               | Type    | Description                              |
| -------------------- | ------- | ---------------------------------------- |
| `commentId`          | string  | Scroll to this specific comment on load. |
| `disableAds`         | boolean | Disable ads in the widget.               |
| `disableLiveReplies` | boolean | Disable live replies.                    |

**`integration` (advanced):**

| Option   | Type        | Description                                                                                       |
| -------- | ----------- | ------------------------------------------------------------------------------------------------- |
| `target` | DOM element | Custom mount point, instead of `#graphcomment`.                                                   |
| `theme`  | string      | Force `'dark'` or `'light'` at load — only applies when your back-office theme setting is `auto`. |
| `font`   | string      | Font family (a Google Font or a system font); takes priority over the back-office setting.        |

**Side panel mode.** Dedicated bundles (`gc_sidePanel.js`, `gc_sidePanel_graphlogin.js`) render the comments in a sliding overlay panel instead of an inline block, configured through a `sidePanel` section:

```javascript
sidePanel: {
  visible: true,          // panel open by default
  width: 600,             // panel width in px (desktop)
  zindex: 99,
  button: { label: 'Comments', background: '#f35b5b' },
  bubble: { background: '#f35b5b', zindex: 98 }
}
```

All the panel's CSS is generated by the bundle — nothing to add to your own stylesheets.

**Runtime commands (advanced):**

| Command                | Signature           | Effect                                                    |
| ---------------------- | ------------------- | --------------------------------------------------------- |
| `__semio__gcSetFont`   | `('Roboto')`        | Change the widget font (Google Font or system font).      |
| `__semio__gcSetDarkBg` | `('#1a1e24' \| '')` | Override the iframe background in dark mode; `''` resets. |

## Next steps

* **[Single Sign-On](./authentication-sso)** — sign your users in with their existing account.
* **[Mobile (WebView)](./mobile-webview)** — the `inapp` flow for native apps.
* **[Comment count](./comment-count)** — show comment counts next to article links.