ARCY AI
BETA

Quickstart

Two paths, three steps. Install arcy.js with NPM or a single HTML snippet, identify your users, and verify the installation from the dashboard.

ARCY is installed by adding arcy.js to your product. There are two paths and three required steps, and the whole thing is designed so a developer can finish without reading anything beyond this page.

Your environment's install snippets, with the real token already filled in, live in the dashboard under Settings > Installation. This page explains the same steps in full.

Everything ARCY does is configured from the dashboard, not from code. There is no config file, no build step, and nothing to redeploy when you change settings.

Required steps

Choose your installation method

  • NPM, for browser apps using a module bundler (Webpack, Vite, Rollup). The recommended path.
  • HTML, for everything else, including tag managers. One snippet pasted before the ending </body> tag.

Pick one. Never install both on the same page.

Install

First, run this in your terminal:

bash
npm install arcy.js

Then import and use the arcy object where your app boots:

js
import arcy from "arcy.js"

arcy.init("YOUR_ENVIRONMENT_TOKEN") // Copy the real token from Settings > Installation
arcy.identify("USER_ID", {
  user_first_name: "USER_FIRST_NAME",
  user_last_name: "USER_LAST_NAME",
  user_email: "USER_EMAIL",
  user_signed_up_at: "USER_SIGNED_UP_AT",
})

Only do this if you're not using NPM. Copy the snippet from Settings > Installation in your dashboard and paste it into your HTML document before the ending </body> tag.

The snippet has two parts:

  1. ARCY's loader script. Minified, self-contained, and already carrying your environment's token. It loads arcy.js asynchronously, so your page load speed is unaffected, and it queues any calls made before the script finishes loading. Paste it exactly as is. You never need to read, edit, version, or host it.
  2. Your identify script. A short, readable script containing the arcy.identify() call. This is the only part you edit.
html
<script>
  arcy.identify("USER_ID", {
    user_first_name: "USER_FIRST_NAME",
    user_last_name: "USER_LAST_NAME",
    user_email: "USER_EMAIL",
    user_signed_up_at: "USER_SIGNED_UP_AT",
  })
</script>

The token in init() identifies one environment (Production, Staging, and so on). It is public by design and appears in your page source, so it is safe to ship. Each environment has its own token; use the environment switcher in the dashboard sidebar to get another environment's snippet.

Replace the placeholders

Replace the placeholders with real, dynamic values from your auth or session layer:

PlaceholderMeaning
USER_IDThe signed-in user's ID in your own database
USER_FIRST_NAMEThe user's first name, as a dynamic value
USER_LAST_NAMEThe user's last name, as a dynamic value
USER_EMAILThe user's real email, as a dynamic value
USER_SIGNED_UP_ATWhen the user signed up. ISO 8601, e.g. 2019-12-11T12:34:56Z

When you are done, click Verify installation on the dashboard's Installation page. It confirms traffic is arriving from your environment and diagnoses the common failure cases specifically: no traffic yet, an unverified origin, or a snippet carrying another environment's token.

Optional steps

Add custom attributes

The attributes object in identify() is technically optional, but the attributes you pass decide which intelligence ARCY can compute. Passing nothing produces a working widget and a nearly useless dashboard.

  • Pass plan_value and plan_cycle to enable revenue-at-risk insights. Without them, ARCY has no revenue figure to attach to a struggling account, and the insight is not degraded, it is impossible.
  • Pass organization_id to get account-level rollups instead of isolated users.
  • Add any custom attribute your product knows about the user.

Custom attributes must be declared before ARCY stores them: define each one under Agent > Attributes in the dashboard, then send it. A key that arrives without a declaration is dropped, counted, and named on Verify installation, never silently stored. This keeps a typo from permanently entering your schema.

Enforce identity verification

Strongly recommended for production. Without it, anyone can open your site, type arcy.identify("someone-elses-id") into the browser console, and read that person's conversation history back out of the widget. Identity verification closes that by having your own server sign each user id with a Secret the browser never sees.

It takes one line on your backend and one extra argument on the front end.

1. Get your Secret

Your environment's Secret is in the dashboard under Agent > Environments. It is shown once when the environment is created and once again each time you rotate it, so store it wherever you keep your other server-side credentials.

The Secret is a server-side credential. Never put it in front-end code, a build environment variable that reaches the browser, a mobile app binary, or a repository. Anyone holding it can sign any user id. The Token you pass to arcy.init() is the public one and is safe in the browser. The Secret is not.

2. Sign the user id on your server

The signature is HMAC-SHA256 of the user id, keyed with the Secret, hex encoded. It covers the user id only, not the attributes, and it is the same recipe Intercom and Segment use, so an existing implementation usually ports directly.

Compute it wherever you already render the page or serve the session, and pass the result to the front end alongside the user id.

js
import { createHmac } from "node:crypto"

const userHash = createHmac("sha256", process.env.ARCY_SECRET)
  .update(String(user.id))
  .digest("hex")
python
import hashlib, hmac, os

user_hash = hmac.new(
    os.environ["ARCY_SECRET"].encode("utf-8"),
    str(user.id).encode("utf-8"),
    hashlib.sha256,
).hexdigest()
ruby
user_hash = OpenSSL::HMAC.hexdigest("SHA256", ENV["ARCY_SECRET"], user.id.to_s)
php
$userHash = hash_hmac('sha256', (string) $user->id, getenv('ARCY_SECRET'));

Sign the exact string you pass to identify(). If your user ids are integers and you call arcy.identify(String(user.id)), sign String(user.id) too. A signature over 42 will not verify a call identifying "42".

3. Pass it to identify()

The hash rides in a third argument, an options object:

js
arcy.identify("USER_ID", {
  user_first_name: "USER_FIRST_NAME",
  user_email: "USER_EMAIL",
}, {
  userHash: "USER_HASH", // computed on your server, never in the browser
})

identifyAnonymous() and updateUser() take no hash. The first asserts no user id, and the second inherits the verification state of the identify() call that came before it.

4. Turn enforcement on

Until you switch it on, verification runs as a dry run: signatures are checked and the result is recorded, but nothing is turned away. That is deliberate, so you can confirm your signing works before it can lock anyone out.

Watch the results, and when they are clean, switch Enforce identity verification on for the environment. From then on, a call whose signature does not verify is not trusted: the session continues as anonymous rather than being attributed to a user it could not prove.

Turn enforcement on only after you see verified sessions arriving. With it on and the signing broken, every user is treated as anonymous until you deploy a fix.

Rotating the Secret

Rotating breaks your backend, not your page, so ARCY accepts signatures made with the previous Secret for 24 hours after a rotation. That window is there so a deploy can follow a rotation without sending your users anonymous in between.

If you rotated because the Secret leaked, do not wait for the window: revoke the previous Secret immediately from the same screen. That takes effect at once, and any signature still made with the old value stops verifying.

Install for unauthenticated users

For public pages with no signed-in user, swap identify() for:

js
arcy.identifyAnonymous()

A unique id is generated and stored in localStorage, then reused on later visits, so a returning anonymous visitor is the same user across sessions.

Anonymous activity consumes credits on the same meter as identified activity. If you put ARCY on a high-traffic public site, understand the cost before you do it, and set the separate anonymous usage cap under Settings > Limits. It bounds anonymous spend without throttling your signed-in users, and setting it to 0 disables anonymous serving entirely.

Installing through a tag manager

The HTML path works unchanged inside a tag manager such as Google Tag Manager:

  1. Create a new Custom HTML tag.
  2. Paste the full HTML snippet from Settings > Installation, both scripts included.
  3. Set the trigger to All Pages, and publish the container.

The loader guards against double-initialization, so a snippet that fires twice (common with tag managers) does not break anything. Tag manager sandboxes that strip <script> tags must allow custom HTML for the snippet to run.

Electron apps and self-hosting the loader are not supported in the beta. An Electron renderer can usually use the NPM path unmodified.

On this page