# Quickstart Source: https://docs.arcyai.com/quickstart Your environment's snippets, with the real token already filled in, live in the dashboard under **Settings > Installation**. No account yet? Start with [Create your account](/getting-started/create-account). Everything ARCY does is configured from the dashboard, not in code. There is no config file, no build step, and nothing to redeploy when you change a setting. ## Required steps ### Add arcy.js to your app Pick your framework. Every path does the same two things: `init()` starts ARCY with your environment token, and `identify()` tells ARCY who the current user is. React Next.js Vue Nuxt Svelte Angular Astro React Router HTML Install the package: Then call ARCY once, where your app starts. In a Vite or Create React App project that is your root component: Install the package: arcy.js runs in the browser only, so keep the call in a client component. App Router Pages Router Add one client component and render it in your root layout: ```tsx title="app/layout.tsx" import { ARCY } from "./arcy" export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ) } ``` Call ARCY once in `_app.tsx`, the component that wraps every page: Install the package: Then call ARCY where you create the app: Install the package: Then add a client plugin. The `.client` in the file name keeps it out of the server render: Install the package: Then call ARCY from your root layout, inside `onMount` so it runs in the browser only: Install the package: Then call ARCY from your root component: Install the package: Then add a script to the layout every page uses. Astro bundles it and runs it in the browser: Install the package: Then call ARCY from your root route, inside an effect so it runs after hydration: No package to install. Use this path when you have no bundler, or when you install through a tag manager. Copy the snippet from **Settings > Installation** in your dashboard and paste it into your HTML before the closing `` tag. It 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 it is. You never need to read, edit, version, or host it. 2. **Your identify script.** A short, readable script with the `arcy.identify()` call. This is the only part you edit. Never put the HTML snippet and the package on the same page. Pick one. The token in `init()` belongs to 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 one. ### Replace the placeholders Only the **Your own auth** tab leaves placeholders behind. Supabase, Clerk, Auth.js and Firebase each read the user out of their own session, so if you picked one of those there is nothing to replace and you can go straight to the next step. Swap the placeholders for real, dynamic values from your auth or session layer: | Placeholder | Meaning | | -------------------- | ---------------------------------------------------------------- | | `USER_ID` | The signed-in user's ID in your own database | | `USER_FIRST_NAME` | The user's first name, as a dynamic value | | `USER_LAST_NAME` | The user's last name, as a dynamic value | | `USER_EMAIL` | The user's real email, as a dynamic value | | `USER_SIGNED_UP_AT` | When the user signed up. ISO 8601, e.g. `2019-12-11T12:34:56Z` | ### Verify the installation Click **Verify installation** on the dashboard's Installation page. It confirms traffic is arriving from your environment and names the common failures one by one: no traffic yet, an unverified origin, or a snippet carrying another environment's token. Everything below on this page also appears on that Installation page, as numbered steps against the environment you have selected. On the Development environment they are marked optional, because Development answers from any address and carries no real users. On any other environment they are the steps that make it safe to ship. ## 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. Node.js Python Ruby PHP ```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, 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 Signatures made with the previous Secret keep verifying for 24 hours, so a deploy can follow a rotation. If the Secret leaked, revoke the previous one immediately from the same screen instead of waiting. See [API key security](/security/api-key-security). ### 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 spends chats 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 `