Identified visitors with metadata and cross-device conversation history.

What are Contacts?

Contacts are identified visitors. When you identify an anonymous visitor with an externalId (your user ID) or email, they become a contact.

Contacts enable:

  • Cross-device support: Same user on desktop and mobile shares conversation history
  • Rich metadata: Attach context like plan type, MRR, company, or lifecycle stage
  • Dashboard visibility: Support agents see user details alongside conversations
  • Persistent identity: Conversations follow the user, not the device

Creating Contacts

Identification Requirements

A contact requires at least one of:

  • externalId: Your internal user ID (recommended)
  • email: User's email address

Both are accepted, but externalId is preferred for robust cross-system tracking.

Using the Component

tsapp/dashboard/layout.tsx
import { IdentifySupportVisitor } from "@cossistant/next";
import { auth } from "@/lib/auth";
import { headers } from "next/headers";
 
export default async function DashboardLayout({ children }) {
  const session = await auth.api.getSession({
    headers: await headers(),
  });
 
  return (
    <div>
      {session?.user && (
        <IdentifySupportVisitor
          externalId={session.user.id}
          email={session.user.email}
          name={session.user.name}
          image={session.user.image}
          metadata={{
            plan: session.user.plan,
            signupDate: session.user.createdAt,
            company: session.user.company,
            mrr: session.user.mrr,
          }}
        />
      )}
      {children}
    </div>
  );
}

Using the Hook

tscomponents/auth-handler.tsx
"use client";
 
import { useVisitor } from "@cossistant/next";
import { useEffect } from "react";
 
export function AuthHandler({ user }) {
  const { visitor, identify } = useVisitor();
 
  useEffect(() => {
    if (user && !visitor?.contact) {
      identify({
        externalId: user.id,
        email: user.email,
        name: user.name,
        image: user.avatar,
        metadata: {
          plan: user.plan,
          signupDate: user.createdAt,
        },
      });
    }
  }, [user, visitor?.contact, identify]);
 
  return null;
}

Contact Metadata

Metadata provides context to support agents during conversations. It appears in your dashboard alongside chat threads.

What to Include

Common metadata fields:

  • plan: Subscription tier (free, pro, enterprise)
  • signupDate: When the user joined
  • company: Organization name
  • mrr: Monthly recurring revenue
  • lifecycleStage: lead, trial, customer, churned
  • lastActive: Last activity timestamp

Metadata Schema

type VisitorMetadata = Record<string, string | number | boolean | null>;

Only primitive values are supported—no nested objects or arrays.

Updating Metadata

Metadata can be updated anytime to reflect user changes:

tscomponents/upgrade-button.tsx
"use client";
 
import { useVisitor } from "@cossistant/next";
 
export function UpgradeButton() {
  const { setVisitorMetadata } = useVisitor();
 
  const handleUpgrade = async () => {
    await upgradeToPro();
 
    // Update metadata so agents see the new plan
    await setVisitorMetadata({
      plan: "pro",
      upgradedAt: new Date().toISOString(),
      mrr: 99,
    });
  };
 
  return <button onClick={handleUpgrade}>Upgrade to Pro</button>;
}

Efficient Metadata Updates

Cossistant hashes metadata before sending updates. If metadata hasn't changed, no API call is made—preventing unnecessary network requests and database writes.

This means you can safely call setVisitorMetadata() or re-render <IdentifySupportVisitor /> without performance concerns.

One Contact, Multiple Visitors

A single contact can have multiple visitors associated with it:

  • Desktop visitor: User on their laptop
  • Mobile visitor: Same user on their phone
  • Tablet visitor: Same user on their iPad

All three visitors share:

  • Conversation history
  • Contact metadata
  • Support context

This provides seamless support across devices—agents see the full picture regardless of where the user reaches out.

Learn More