@census-ai/census-sdk 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var u="https://api.census.ai",n=class{constructor(e){this.currentUserId=null;if(!e.apiKey)throw new Error("Census: apiKey is required");["cs_live_","cs_test_","op_live_","op_test_"].some(s=>e.apiKey.startsWith(s))||console.warn('Census: API key should start with "cs_live_" or "cs_test_"'),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl||u,this.debug=e.debug||false,this.log("Initialized with base URL:",this.baseUrl);}async identify(e){if(!e.userId)throw new Error("Census: userId is required for identify()");this.currentUserId=e.userId,await this.request("/api/sdk/identify","POST",{userId:e.userId,email:e.email,name:e.name,avatarUrl:e.avatarUrl,metadata:e.metadata,organizationId:e.organizationId,organizationName:e.organizationName,organizationDomain:e.organizationDomain,organizationPlan:e.organizationPlan}),this.log("User identified:",e.userId);}reset(){this.currentUserId=null,this.log("User identity reset");}async submitFeedback(e){let t=["feedback","bug_report","feature_request","article_rating"];if(!e.type||!t.includes(e.type))throw new Error(`Census: type must be one of: ${t.join(", ")}`);if(e.type==="article_rating"){if(e.rating===void 0&&e.helpful===void 0)throw new Error("Census: article_rating requires rating or helpful field")}else if(!e.message)throw new Error("Census: message is required for this feedback type");let s=await this.request("/api/sdk/feedback","POST",{type:e.type,message:e.message,rating:e.rating,helpful:e.helpful,userId:this.currentUserId,articleId:e.articleId,pageUrl:typeof window<"u"?window.location.href:void 0,metadata:e.metadata});return this.log("Feedback submitted:",s.feedbackId),{feedbackId:s.feedbackId}}async getArticles(e){let t=new URLSearchParams;e?.category&&t.set("category",e.category),e?.search&&t.set("search",e.search),e?.limit&&t.set("limit",String(e.limit)),e?.offset&&t.set("offset",String(e.offset));let s=t.toString(),a=`/api/sdk/articles${s?`?${s}`:""}`,r=await this.request(a,"GET");return this.log("Fetched articles:",r.articles.length),r}async getArticle(e){try{let t=await this.request(`/api/sdk/articles/${encodeURIComponent(e)}`,"GET");return this.log("Fetched article:",e),t.article}catch(t){if(t.status===404)return null;throw t}}async getRequests(e){if(!this.currentUserId)throw new Error("Census: User must be identified before fetching requests. Call identify() first.");let t=new URLSearchParams;t.set("userId",this.currentUserId),e?.status&&t.set("status",e.status),e?.type&&t.set("type",e.type),e?.limit&&t.set("limit",String(e.limit)),e?.offset&&t.set("offset",String(e.offset));let s=await this.request(`/api/sdk/requests?${t.toString()}`,"GET");return this.log("Fetched requests:",s.requests.length),s}async track(e,t){if(!e)throw new Error("Census: eventType is required for track()");await this.request("/api/sdk/events","POST",{eventType:e,userId:this.currentUserId,properties:t}),this.log("Event tracked:",e);}async trackBatch(e){if(!e.events||e.events.length===0)throw new Error("Census: at least one event is required");if(e.events.length>100)throw new Error("Census: maximum 100 events per batch");let t=e.events.map(s=>({eventType:s.eventType,userId:this.currentUserId,articleId:s.articleId,featureId:s.featureId,properties:s.properties}));await this.request("/api/sdk/events","POST",{events:t}),this.log("Batch events tracked:",e.events.length);}getCurrentUserId(){return this.currentUserId}isIdentified(){return this.currentUserId!==null}async request(e,t,s){let a=`${this.baseUrl}${e}`,r={"X-Census-Key":this.apiKey};s&&(r["Content-Type"]="application/json"),this.log(`${t} ${e}`,s);let i=await fetch(a,{method:t,headers:r,body:s?JSON.stringify(s):void 0});if(!i.ok){let o=`Request failed with status ${i.status}`;try{o=(await i.json()).error||o;}catch{}throw {error:o,status:i.status}}return i.json()}log(...e){this.debug&&console.log("[Census]",...e);}};function d(c){return new n(c)}
2
- exports.CensusClient=n;exports.createCensus=d;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var d="https://api.census.ai",a=class{constructor(e){this.currentUserId=null;if(!e.apiKey)throw new Error("Census: apiKey is required");["cs_live_","cs_test_","op_live_","op_test_"].some(t=>e.apiKey.startsWith(t))||console.warn('Census: API key should start with "cs_live_" or "cs_test_"'),this.apiKey=e.apiKey,this.baseUrl=e.baseUrl||d,this.debug=e.debug||false,this.log("Initialized with base URL:",this.baseUrl);}async identify(e){if(!e.userId)throw new Error("Census: userId is required for identify()");this.currentUserId=e.userId,await this.request("/api/sdk/identify","POST",{userId:e.userId,email:e.email,name:e.name,avatarUrl:e.avatarUrl,metadata:e.metadata,organizationId:e.organizationId,organizationName:e.organizationName,organizationDomain:e.organizationDomain,organizationPlan:e.organizationPlan}),this.log("User identified:",e.userId);}reset(){this.currentUserId=null,this.log("User identity reset");}async submitFeedback(e){let s=["feedback","bug_report","feature_request","article_rating"];if(!e.type||!s.includes(e.type))throw new Error(`Census: type must be one of: ${s.join(", ")}`);if(e.type==="article_rating"){if(e.rating===void 0&&e.helpful===void 0)throw new Error("Census: article_rating requires rating or helpful field")}else if(!e.message)throw new Error("Census: message is required for this feedback type");let t=await this.request("/api/sdk/feedback","POST",{type:e.type,message:e.message,rating:e.rating,helpful:e.helpful,userId:this.currentUserId,articleId:e.articleId,pageUrl:typeof window<"u"?window.location.href:void 0,metadata:e.metadata});return this.log("Feedback submitted:",t.feedbackId),{feedbackId:t.feedbackId}}async getArticles(e){let s=new URLSearchParams;e?.category&&s.set("category",e.category),e?.search&&s.set("search",e.search),e?.limit&&s.set("limit",String(e.limit)),e?.offset&&s.set("offset",String(e.offset));let t=s.toString(),r=`/api/sdk/articles${t?`?${t}`:""}`,i=await this.request(r,"GET");return this.log("Fetched articles:",i.articles.length),i}async getArticle(e){try{let s=await this.request(`/api/sdk/articles/${encodeURIComponent(e)}`,"GET");return this.log("Fetched article:",e),s.article}catch(s){if(s.status===404)return null;throw s}}async getFeatureGroups(){let e=await this.request("/api/sdk/feature-groups","GET");return this.log("Fetched feature groups:",e.feature_groups.length),e}async getRequests(e){if(!this.currentUserId)throw new Error("Census: User must be identified before fetching requests. Call identify() first.");let s=new URLSearchParams;s.set("userId",this.currentUserId),e?.status&&s.set("status",e.status),e?.type&&s.set("type",e.type),e?.limit&&s.set("limit",String(e.limit)),e?.offset&&s.set("offset",String(e.offset));let t=await this.request(`/api/sdk/requests?${s.toString()}`,"GET");return this.log("Fetched requests:",t.requests.length),t}async vote(e){if(!this.currentUserId)throw new Error("Census: User must be identified before voting. Call identify() first.");if(!e)throw new Error("Census: feedbackId is required for vote()");let s=await this.request("/api/sdk/requests/vote","POST",{feedbackId:e,userId:this.currentUserId});return this.log("Vote result:",s.action,"for feedback:",e),s}async track(e,s){if(!e)throw new Error("Census: eventType is required for track()");await this.request("/api/sdk/events","POST",{eventType:e,userId:this.currentUserId,properties:s}),this.log("Event tracked:",e);}async trackBatch(e){if(!e.events||e.events.length===0)throw new Error("Census: at least one event is required");if(e.events.length>100)throw new Error("Census: maximum 100 events per batch");let s=e.events.map(t=>({eventType:t.eventType,userId:this.currentUserId,articleId:t.articleId,featureId:t.featureId,properties:t.properties}));await this.request("/api/sdk/events","POST",{events:s}),this.log("Batch events tracked:",e.events.length);}async getGuides(){let e=new URLSearchParams;this.currentUserId&&e.set("userId",this.currentUserId);let s=e.toString(),t=`/api/sdk/guides${s?`?${s}`:""}`,r=await this.request(t,"GET");return this.log("Fetched guides:",r.guides.length),r}async getGuide(e){try{let s=new URLSearchParams;this.currentUserId&&s.set("userId",this.currentUserId);let t=s.toString(),r=`/api/sdk/guides/${encodeURIComponent(e)}${t?`?${t}`:""}`,i=await this.request(r,"GET");return this.log("Fetched guide:",e),i.guide}catch(s){if(s.status===404)return null;throw s}}async trackGuideEvent(e){if(!e.guideId||!e.eventType||!e.sessionId)throw new Error("Census: guideId, eventType, and sessionId are required for trackGuideEvent()");await this.request("/api/sdk/guides/events","POST",{guideId:e.guideId,eventType:e.eventType,stepId:e.stepId,stepIndex:e.stepIndex,pageUrl:e.pageUrl||(typeof window<"u"?window.location.href:void 0),sessionId:e.sessionId,userId:e.userId||this.currentUserId,metadata:e.metadata}),this.log("Guide event tracked:",e.eventType,e.guideId);}async markGuideCompleted(e){if(!e)throw new Error("Census: guideId is required for markGuideCompleted()");if(!this.currentUserId)throw new Error("Census: User must be identified before marking guides complete. Call identify() first.");await this.request("/api/sdk/guides/complete","POST",{guideId:e,userId:this.currentUserId}),this.log("Guide marked completed:",e);}getCurrentUserId(){return this.currentUserId}isIdentified(){return this.currentUserId!==null}async request(e,s,t){let r=`${this.baseUrl}${e}`,i={"X-Census-Key":this.apiKey};t&&(i["Content-Type"]="application/json"),this.log(`${s} ${e}`,t);let n=await fetch(r,{method:s,headers:i,body:t?JSON.stringify(t):void 0});if(!n.ok){let o=`Request failed with status ${n.status}`;try{o=(await n.json()).error||o;}catch{}throw {error:o,status:n.status}}return n.json()}log(...e){this.debug&&console.log("[Census]",...e);}};function c(u){return new a(u)}
2
+ exports.CensusClient=a;exports.createCensus=c;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"names":["DEFAULT_BASE_URL","CensusClient","config","prefix","user","options","validTypes","response","params","queryString","url","slugOrId","error","eventType","properties","events","event","path","method","body","headers","errorMessage","args","createCensus"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n CensusConfig,\n UserIdentity,\n FeedbackOptions,\n ArticlesOptions,\n ArticlesResponse,\n Article,\n RequestsOptions,\n RequestsResponse,\n BatchEventsOptions,\n CensusError,\n} from './types';\n\n/**\n * Default API base URL\n */\nconst DEFAULT_BASE_URL = 'https://api.census.ai';\n\n/**\n * Census SDK Client\n *\n * The main client for interacting with the Census API.\n * Use `createCensus()` to create an instance.\n *\n * @example\n * ```typescript\n * import { createCensus } from '@census-ai/census-sdk';\n *\n * const census = createCensus({ apiKey: 'cs_live_xxx' });\n *\n * await census.identify({ userId: 'user_123', email: 'user@example.com' });\n * await census.submitFeedback({ type: 'bug_report', message: 'Button is broken' });\n * ```\n */\nexport class CensusClient {\n private apiKey: string;\n private baseUrl: string;\n private debug: boolean;\n private currentUserId: string | null = null;\n\n constructor(config: CensusConfig) {\n if (!config.apiKey) {\n throw new Error('Census: apiKey is required');\n }\n\n // Support both new (cs_) and legacy (op_) key prefixes\n const validPrefixes = ['cs_live_', 'cs_test_', 'op_live_', 'op_test_'];\n if (!validPrefixes.some(prefix => config.apiKey.startsWith(prefix))) {\n console.warn('Census: API key should start with \"cs_live_\" or \"cs_test_\"');\n }\n\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;\n this.debug = config.debug || false;\n\n this.log('Initialized with base URL:', this.baseUrl);\n }\n\n /**\n * Identify a user for tracking purposes.\n * Call this when a user logs in or when you have user information.\n *\n * @param user - User identity information\n *\n * @example\n * ```typescript\n * await census.identify({\n * userId: 'user_123',\n * email: 'john@example.com',\n * name: 'John Doe',\n * organizationId: 'org_456',\n * organizationName: 'Acme Inc',\n * });\n * ```\n */\n async identify(user: UserIdentity): Promise<void> {\n if (!user.userId) {\n throw new Error('Census: userId is required for identify()');\n }\n\n this.currentUserId = user.userId;\n\n await this.request('/api/sdk/identify', 'POST', {\n userId: user.userId,\n email: user.email,\n name: user.name,\n avatarUrl: user.avatarUrl,\n metadata: user.metadata,\n organizationId: user.organizationId,\n organizationName: user.organizationName,\n organizationDomain: user.organizationDomain,\n organizationPlan: user.organizationPlan,\n });\n\n this.log('User identified:', user.userId);\n }\n\n /**\n * Clear the current user identity.\n * Call this when a user logs out.\n */\n reset(): void {\n this.currentUserId = null;\n this.log('User identity reset');\n }\n\n /**\n * Submit feedback, bug report, or feature request.\n *\n * @param options - Feedback options\n *\n * @example\n * ```typescript\n * // Submit a bug report\n * await census.submitFeedback({\n * type: 'bug_report',\n * message: 'The submit button is not working on Firefox',\n * });\n *\n * // Submit a feature request\n * await census.submitFeedback({\n * type: 'feature_request',\n * message: 'It would be great to have dark mode support',\n * });\n *\n * // Rate an article\n * await census.submitFeedback({\n * type: 'article_rating',\n * articleId: 'article_123',\n * helpful: true,\n * rating: 5,\n * });\n * ```\n */\n async submitFeedback(options: FeedbackOptions): Promise<{ feedbackId: string }> {\n const validTypes = ['feedback', 'bug_report', 'feature_request', 'article_rating'];\n if (!options.type || !validTypes.includes(options.type)) {\n throw new Error(`Census: type must be one of: ${validTypes.join(', ')}`);\n }\n\n if (options.type === 'article_rating') {\n if (options.rating === undefined && options.helpful === undefined) {\n throw new Error('Census: article_rating requires rating or helpful field');\n }\n } else if (!options.message) {\n throw new Error('Census: message is required for this feedback type');\n }\n\n const response = await this.request<{ success: boolean; feedbackId: string }>(\n '/api/sdk/feedback',\n 'POST',\n {\n type: options.type,\n message: options.message,\n rating: options.rating,\n helpful: options.helpful,\n userId: this.currentUserId,\n articleId: options.articleId,\n pageUrl: typeof window !== 'undefined' ? window.location.href : undefined,\n metadata: options.metadata,\n }\n );\n\n this.log('Feedback submitted:', response.feedbackId);\n return { feedbackId: response.feedbackId };\n }\n\n /**\n * Fetch published articles from the knowledge base.\n *\n * @param options - Query options\n * @returns Articles and pagination info\n *\n * @example\n * ```typescript\n * // Get all articles\n * const { articles } = await census.getArticles();\n *\n * // Search articles\n * const { articles } = await census.getArticles({ search: 'getting started' });\n *\n * // Filter by category\n * const { articles } = await census.getArticles({ category: 'guides' });\n * ```\n */\n async getArticles(options?: ArticlesOptions): Promise<ArticlesResponse> {\n const params = new URLSearchParams();\n if (options?.category) params.set('category', options.category);\n if (options?.search) params.set('search', options.search);\n if (options?.limit) params.set('limit', String(options.limit));\n if (options?.offset) params.set('offset', String(options.offset));\n\n const queryString = params.toString();\n const url = `/api/sdk/articles${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.request<ArticlesResponse>(url, 'GET');\n this.log('Fetched articles:', response.articles.length);\n return response;\n }\n\n /**\n * Fetch a single article by slug or ID.\n *\n * @param slugOrId - Article slug or ID\n * @returns Article or null if not found\n *\n * @example\n * ```typescript\n * const article = await census.getArticle('getting-started');\n * if (article) {\n * console.log(article.title, article.content_html);\n * }\n * ```\n */\n async getArticle(slugOrId: string): Promise<Article | null> {\n try {\n const response = await this.request<{ article: Article }>(\n `/api/sdk/articles/${encodeURIComponent(slugOrId)}`,\n 'GET'\n );\n this.log('Fetched article:', slugOrId);\n return response.article;\n } catch (error) {\n if ((error as CensusError).status === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch the current user's submitted requests (feedback, bugs, feature requests).\n * Requires a user to be identified first.\n *\n * @param options - Query options\n * @returns Requests and pagination info\n *\n * @example\n * ```typescript\n * // Get all requests for the current user\n * const { requests } = await census.getRequests();\n *\n * // Filter by status\n * const { requests } = await census.getRequests({ status: 'in_progress' });\n *\n * // Filter by type\n * const { requests } = await census.getRequests({ type: 'bug_report' });\n * ```\n */\n async getRequests(options?: RequestsOptions): Promise<RequestsResponse> {\n if (!this.currentUserId) {\n throw new Error('Census: User must be identified before fetching requests. Call identify() first.');\n }\n\n const params = new URLSearchParams();\n params.set('userId', this.currentUserId);\n if (options?.status) params.set('status', options.status);\n if (options?.type) params.set('type', options.type);\n if (options?.limit) params.set('limit', String(options.limit));\n if (options?.offset) params.set('offset', String(options.offset));\n\n const response = await this.request<RequestsResponse>(\n `/api/sdk/requests?${params.toString()}`,\n 'GET'\n );\n this.log('Fetched requests:', response.requests.length);\n return response;\n }\n\n /**\n * Track a custom analytics event.\n *\n * @param eventType - Name of the event\n * @param properties - Additional event properties\n *\n * @example\n * ```typescript\n * // Track a button click\n * await census.track('button_clicked', { buttonId: 'submit-form' });\n *\n * // Track a page view\n * await census.track('page_viewed', { page: '/pricing' });\n * ```\n */\n async track(eventType: string, properties?: Record<string, unknown>): Promise<void> {\n if (!eventType) {\n throw new Error('Census: eventType is required for track()');\n }\n\n await this.request('/api/sdk/events', 'POST', {\n eventType,\n userId: this.currentUserId,\n properties,\n });\n\n this.log('Event tracked:', eventType);\n }\n\n /**\n * Track multiple events in a single request.\n * More efficient than calling track() multiple times.\n *\n * @param events - Array of events to track\n *\n * @example\n * ```typescript\n * await census.trackBatch({\n * events: [\n * { eventType: 'page_viewed', properties: { page: '/home' } },\n * { eventType: 'button_clicked', properties: { button: 'cta' } },\n * ],\n * });\n * ```\n */\n async trackBatch(options: BatchEventsOptions): Promise<void> {\n if (!options.events || options.events.length === 0) {\n throw new Error('Census: at least one event is required');\n }\n\n if (options.events.length > 100) {\n throw new Error('Census: maximum 100 events per batch');\n }\n\n const events = options.events.map((event) => ({\n eventType: event.eventType,\n userId: this.currentUserId,\n articleId: event.articleId,\n featureId: event.featureId,\n properties: event.properties,\n }));\n\n await this.request('/api/sdk/events', 'POST', { events });\n\n this.log('Batch events tracked:', options.events.length);\n }\n\n /**\n * Get the current identified user ID\n */\n getCurrentUserId(): string | null {\n return this.currentUserId;\n }\n\n /**\n * Check if a user is currently identified\n */\n isIdentified(): boolean {\n return this.currentUserId !== null;\n }\n\n /**\n * Make an API request\n */\n private async request<T>(path: string, method: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n const headers: Record<string, string> = {\n 'X-Census-Key': this.apiKey,\n };\n\n if (body) {\n headers['Content-Type'] = 'application/json';\n }\n\n this.log(`${method} ${path}`, body);\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n let errorMessage = `Request failed with status ${response.status}`;\n try {\n const errorData = await response.json();\n errorMessage = errorData.error || errorMessage;\n } catch {\n // Use default error message\n }\n\n const error: CensusError = {\n error: errorMessage,\n status: response.status,\n };\n throw error;\n }\n\n return response.json();\n }\n\n /**\n * Log debug messages\n */\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.log('[Census]', ...args);\n }\n }\n}\n\n/**\n * Create a new Census SDK client.\n *\n * @param config - Configuration options\n * @returns Census client instance\n *\n * @example\n * ```typescript\n * import { createCensus } from '@census-ai/census-sdk';\n *\n * const census = createCensus({\n * apiKey: 'cs_live_your_key_here',\n * debug: true, // Enable debug logging\n * });\n * ```\n */\nexport function createCensus(config: CensusConfig): CensusClient {\n return new CensusClient(config);\n}\n"]}
1
+ {"version":3,"sources":["../src/client.ts"],"names":["DEFAULT_BASE_URL","CensusClient","config","prefix","user","options","validTypes","response","params","queryString","url","slugOrId","error","feedbackId","eventType","properties","events","event","guideId","path","method","body","headers","errorMessage","args","createCensus"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n CensusConfig,\n UserIdentity,\n FeedbackOptions,\n ArticlesOptions,\n ArticlesResponse,\n Article,\n RequestsOptions,\n RequestsResponse,\n BatchEventsOptions,\n CensusError,\n Guide,\n GuidesResponse,\n GuideAnalyticsEvent,\n FeatureGroupsResponse,\n} from './types';\n\n/**\n * Default API base URL\n */\nconst DEFAULT_BASE_URL = 'https://api.census.ai';\n\n/**\n * Census SDK Client\n *\n * The main client for interacting with the Census API.\n * Use `createCensus()` to create an instance.\n *\n * @example\n * ```typescript\n * import { createCensus } from '@census-ai/census-sdk';\n *\n * const census = createCensus({ apiKey: 'cs_live_xxx' });\n *\n * await census.identify({ userId: 'user_123', email: 'user@example.com' });\n * await census.submitFeedback({ type: 'bug_report', message: 'Button is broken' });\n * ```\n */\nexport class CensusClient {\n private apiKey: string;\n private baseUrl: string;\n private debug: boolean;\n private currentUserId: string | null = null;\n\n constructor(config: CensusConfig) {\n if (!config.apiKey) {\n throw new Error('Census: apiKey is required');\n }\n\n // Support both new (cs_) and legacy (op_) key prefixes\n const validPrefixes = ['cs_live_', 'cs_test_', 'op_live_', 'op_test_'];\n if (!validPrefixes.some(prefix => config.apiKey.startsWith(prefix))) {\n console.warn('Census: API key should start with \"cs_live_\" or \"cs_test_\"');\n }\n\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;\n this.debug = config.debug || false;\n\n this.log('Initialized with base URL:', this.baseUrl);\n }\n\n /**\n * Identify a user for tracking purposes.\n * Call this when a user logs in or when you have user information.\n *\n * @param user - User identity information\n *\n * @example\n * ```typescript\n * await census.identify({\n * userId: 'user_123',\n * email: 'john@example.com',\n * name: 'John Doe',\n * organizationId: 'org_456',\n * organizationName: 'Acme Inc',\n * });\n * ```\n */\n async identify(user: UserIdentity): Promise<void> {\n if (!user.userId) {\n throw new Error('Census: userId is required for identify()');\n }\n\n this.currentUserId = user.userId;\n\n await this.request('/api/sdk/identify', 'POST', {\n userId: user.userId,\n email: user.email,\n name: user.name,\n avatarUrl: user.avatarUrl,\n metadata: user.metadata,\n organizationId: user.organizationId,\n organizationName: user.organizationName,\n organizationDomain: user.organizationDomain,\n organizationPlan: user.organizationPlan,\n });\n\n this.log('User identified:', user.userId);\n }\n\n /**\n * Clear the current user identity.\n * Call this when a user logs out.\n */\n reset(): void {\n this.currentUserId = null;\n this.log('User identity reset');\n }\n\n /**\n * Submit feedback, bug report, or feature request.\n *\n * @param options - Feedback options\n *\n * @example\n * ```typescript\n * // Submit a bug report\n * await census.submitFeedback({\n * type: 'bug_report',\n * message: 'The submit button is not working on Firefox',\n * });\n *\n * // Submit a feature request\n * await census.submitFeedback({\n * type: 'feature_request',\n * message: 'It would be great to have dark mode support',\n * });\n *\n * // Rate an article\n * await census.submitFeedback({\n * type: 'article_rating',\n * articleId: 'article_123',\n * helpful: true,\n * rating: 5,\n * });\n * ```\n */\n async submitFeedback(options: FeedbackOptions): Promise<{ feedbackId: string }> {\n const validTypes = ['feedback', 'bug_report', 'feature_request', 'article_rating'];\n if (!options.type || !validTypes.includes(options.type)) {\n throw new Error(`Census: type must be one of: ${validTypes.join(', ')}`);\n }\n\n if (options.type === 'article_rating') {\n if (options.rating === undefined && options.helpful === undefined) {\n throw new Error('Census: article_rating requires rating or helpful field');\n }\n } else if (!options.message) {\n throw new Error('Census: message is required for this feedback type');\n }\n\n const response = await this.request<{ success: boolean; feedbackId: string }>(\n '/api/sdk/feedback',\n 'POST',\n {\n type: options.type,\n message: options.message,\n rating: options.rating,\n helpful: options.helpful,\n userId: this.currentUserId,\n articleId: options.articleId,\n pageUrl: typeof window !== 'undefined' ? window.location.href : undefined,\n metadata: options.metadata,\n }\n );\n\n this.log('Feedback submitted:', response.feedbackId);\n return { feedbackId: response.feedbackId };\n }\n\n /**\n * Fetch published articles from the knowledge base.\n *\n * @param options - Query options\n * @returns Articles and pagination info\n *\n * @example\n * ```typescript\n * // Get all articles\n * const { articles } = await census.getArticles();\n *\n * // Search articles\n * const { articles } = await census.getArticles({ search: 'getting started' });\n *\n * // Filter by category\n * const { articles } = await census.getArticles({ category: 'guides' });\n * ```\n */\n async getArticles(options?: ArticlesOptions): Promise<ArticlesResponse> {\n const params = new URLSearchParams();\n if (options?.category) params.set('category', options.category);\n if (options?.search) params.set('search', options.search);\n if (options?.limit) params.set('limit', String(options.limit));\n if (options?.offset) params.set('offset', String(options.offset));\n\n const queryString = params.toString();\n const url = `/api/sdk/articles${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.request<ArticlesResponse>(url, 'GET');\n this.log('Fetched articles:', response.articles.length);\n return response;\n }\n\n /**\n * Fetch a single article by slug or ID.\n *\n * @param slugOrId - Article slug or ID\n * @returns Article or null if not found\n *\n * @example\n * ```typescript\n * const article = await census.getArticle('getting-started');\n * if (article) {\n * console.log(article.title, article.content_html);\n * }\n * ```\n */\n async getArticle(slugOrId: string): Promise<Article | null> {\n try {\n const response = await this.request<{ article: Article }>(\n `/api/sdk/articles/${encodeURIComponent(slugOrId)}`,\n 'GET'\n );\n this.log('Fetched article:', slugOrId);\n return response.article;\n } catch (error) {\n if ((error as CensusError).status === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch feature groups with their features and article counts.\n * Used for navigation in the knowledge base.\n *\n * @returns Feature groups with nested features\n *\n * @example\n * ```typescript\n * const { feature_groups } = await census.getFeatureGroups();\n * feature_groups.forEach(group => {\n * console.log(group.name, group.features.length);\n * });\n * ```\n */\n async getFeatureGroups(): Promise<FeatureGroupsResponse> {\n const response = await this.request<FeatureGroupsResponse>(\n '/api/sdk/feature-groups',\n 'GET'\n );\n this.log('Fetched feature groups:', response.feature_groups.length);\n return response;\n }\n\n /**\n * Fetch the current user's submitted requests (feedback, bugs, feature requests).\n * Requires a user to be identified first.\n *\n * @param options - Query options\n * @returns Requests and pagination info\n *\n * @example\n * ```typescript\n * // Get all requests for the current user\n * const { requests } = await census.getRequests();\n *\n * // Filter by status\n * const { requests } = await census.getRequests({ status: 'in_progress' });\n *\n * // Filter by type\n * const { requests } = await census.getRequests({ type: 'bug_report' });\n * ```\n */\n async getRequests(options?: RequestsOptions): Promise<RequestsResponse> {\n if (!this.currentUserId) {\n throw new Error('Census: User must be identified before fetching requests. Call identify() first.');\n }\n\n const params = new URLSearchParams();\n params.set('userId', this.currentUserId);\n if (options?.status) params.set('status', options.status);\n if (options?.type) params.set('type', options.type);\n if (options?.limit) params.set('limit', String(options.limit));\n if (options?.offset) params.set('offset', String(options.offset));\n\n const response = await this.request<RequestsResponse>(\n `/api/sdk/requests?${params.toString()}`,\n 'GET'\n );\n this.log('Fetched requests:', response.requests.length);\n return response;\n }\n\n /**\n * Vote on a feedback request (toggle).\n * If the user has already voted, removes the vote.\n * If the user hasn't voted, adds a vote.\n *\n * @param feedbackId - ID of the feedback to vote on\n * @returns Vote result with action taken and new vote count\n *\n * @example\n * ```typescript\n * // Vote on a feedback request\n * const result = await census.vote('feedback-id-123');\n * console.log(result.action); // 'added' or 'removed'\n * console.log(result.vote_count); // 5\n * console.log(result.user_has_voted); // true\n * ```\n */\n async vote(feedbackId: string): Promise<{\n success: boolean;\n action: 'added' | 'removed';\n vote_count: number;\n user_has_voted: boolean;\n }> {\n if (!this.currentUserId) {\n throw new Error('Census: User must be identified before voting. Call identify() first.');\n }\n\n if (!feedbackId) {\n throw new Error('Census: feedbackId is required for vote()');\n }\n\n const response = await this.request<{\n success: boolean;\n action: 'added' | 'removed';\n vote_count: number;\n user_has_voted: boolean;\n }>('/api/sdk/requests/vote', 'POST', {\n feedbackId,\n userId: this.currentUserId,\n });\n\n this.log('Vote result:', response.action, 'for feedback:', feedbackId);\n return response;\n }\n\n /**\n * Track a custom analytics event.\n *\n * @param eventType - Name of the event\n * @param properties - Additional event properties\n *\n * @example\n * ```typescript\n * // Track a button click\n * await census.track('button_clicked', { buttonId: 'submit-form' });\n *\n * // Track a page view\n * await census.track('page_viewed', { page: '/pricing' });\n * ```\n */\n async track(eventType: string, properties?: Record<string, unknown>): Promise<void> {\n if (!eventType) {\n throw new Error('Census: eventType is required for track()');\n }\n\n await this.request('/api/sdk/events', 'POST', {\n eventType,\n userId: this.currentUserId,\n properties,\n });\n\n this.log('Event tracked:', eventType);\n }\n\n /**\n * Track multiple events in a single request.\n * More efficient than calling track() multiple times.\n *\n * @param events - Array of events to track\n *\n * @example\n * ```typescript\n * await census.trackBatch({\n * events: [\n * { eventType: 'page_viewed', properties: { page: '/home' } },\n * { eventType: 'button_clicked', properties: { button: 'cta' } },\n * ],\n * });\n * ```\n */\n async trackBatch(options: BatchEventsOptions): Promise<void> {\n if (!options.events || options.events.length === 0) {\n throw new Error('Census: at least one event is required');\n }\n\n if (options.events.length > 100) {\n throw new Error('Census: maximum 100 events per batch');\n }\n\n const events = options.events.map((event) => ({\n eventType: event.eventType,\n userId: this.currentUserId,\n articleId: event.articleId,\n featureId: event.featureId,\n properties: event.properties,\n }));\n\n await this.request('/api/sdk/events', 'POST', { events });\n\n this.log('Batch events tracked:', options.events.length);\n }\n\n /**\n * Fetch available guides for the current user.\n * Returns guides that match the user's context and haven't been completed.\n *\n * @returns Guides and list of completed guide IDs\n *\n * @example\n * ```typescript\n * const { guides, completedGuides } = await census.getGuides();\n * guides.forEach(guide => console.log(guide.name));\n * ```\n */\n async getGuides(): Promise<GuidesResponse> {\n const params = new URLSearchParams();\n if (this.currentUserId) {\n params.set('userId', this.currentUserId);\n }\n\n const queryString = params.toString();\n const url = `/api/sdk/guides${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.request<GuidesResponse>(url, 'GET');\n this.log('Fetched guides:', response.guides.length);\n return response;\n }\n\n /**\n * Fetch a single guide by slug or ID.\n *\n * @param slugOrId - Guide slug or ID\n * @returns Guide or null if not found\n *\n * @example\n * ```typescript\n * const guide = await census.getGuide('onboarding-tour');\n * if (guide) {\n * console.log(guide.name, guide.guide_steps.length);\n * }\n * ```\n */\n async getGuide(slugOrId: string): Promise<Guide | null> {\n try {\n const params = new URLSearchParams();\n if (this.currentUserId) {\n params.set('userId', this.currentUserId);\n }\n\n const queryString = params.toString();\n const url = `/api/sdk/guides/${encodeURIComponent(slugOrId)}${queryString ? `?${queryString}` : ''}`;\n\n const response = await this.request<{ guide: Guide }>(url, 'GET');\n this.log('Fetched guide:', slugOrId);\n return response.guide;\n } catch (error) {\n if ((error as CensusError).status === 404) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Track a guide analytics event.\n * Used to track user progress through guides.\n *\n * @param event - Guide analytics event\n *\n * @example\n * ```typescript\n * await census.trackGuideEvent({\n * guideId: 'guide_123',\n * eventType: 'step_completed',\n * stepId: 'step_456',\n * stepIndex: 2,\n * sessionId: 'session_789',\n * });\n * ```\n */\n async trackGuideEvent(event: GuideAnalyticsEvent): Promise<void> {\n if (!event.guideId || !event.eventType || !event.sessionId) {\n throw new Error('Census: guideId, eventType, and sessionId are required for trackGuideEvent()');\n }\n\n await this.request('/api/sdk/guides/events', 'POST', {\n guideId: event.guideId,\n eventType: event.eventType,\n stepId: event.stepId,\n stepIndex: event.stepIndex,\n pageUrl: event.pageUrl || (typeof window !== 'undefined' ? window.location.href : undefined),\n sessionId: event.sessionId,\n userId: event.userId || this.currentUserId,\n metadata: event.metadata,\n });\n\n this.log('Guide event tracked:', event.eventType, event.guideId);\n }\n\n /**\n * Mark a guide as completed for the current user.\n * Prevents the guide from showing again.\n *\n * @param guideId - ID of the guide to mark as completed\n *\n * @example\n * ```typescript\n * await census.markGuideCompleted('guide_123');\n * ```\n */\n async markGuideCompleted(guideId: string): Promise<void> {\n if (!guideId) {\n throw new Error('Census: guideId is required for markGuideCompleted()');\n }\n\n if (!this.currentUserId) {\n throw new Error('Census: User must be identified before marking guides complete. Call identify() first.');\n }\n\n await this.request('/api/sdk/guides/complete', 'POST', {\n guideId,\n userId: this.currentUserId,\n });\n\n this.log('Guide marked completed:', guideId);\n }\n\n /**\n * Get the current identified user ID\n */\n getCurrentUserId(): string | null {\n return this.currentUserId;\n }\n\n /**\n * Check if a user is currently identified\n */\n isIdentified(): boolean {\n return this.currentUserId !== null;\n }\n\n /**\n * Make an API request\n */\n private async request<T>(path: string, method: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n const headers: Record<string, string> = {\n 'X-Census-Key': this.apiKey,\n };\n\n if (body) {\n headers['Content-Type'] = 'application/json';\n }\n\n this.log(`${method} ${path}`, body);\n\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n let errorMessage = `Request failed with status ${response.status}`;\n try {\n const errorData = await response.json();\n errorMessage = errorData.error || errorMessage;\n } catch {\n // Use default error message\n }\n\n const error: CensusError = {\n error: errorMessage,\n status: response.status,\n };\n throw error;\n }\n\n return response.json();\n }\n\n /**\n * Log debug messages\n */\n private log(...args: unknown[]): void {\n if (this.debug) {\n console.log('[Census]', ...args);\n }\n }\n}\n\n/**\n * Create a new Census SDK client.\n *\n * @param config - Configuration options\n * @returns Census client instance\n *\n * @example\n * ```typescript\n * import { createCensus } from '@census-ai/census-sdk';\n *\n * const census = createCensus({\n * apiKey: 'cs_live_your_key_here',\n * debug: true, // Enable debug logging\n * });\n * ```\n */\nexport function createCensus(config: CensusConfig): CensusClient {\n return new CensusClient(config);\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -186,6 +186,21 @@ interface Request {
186
186
  rating: number | null;
187
187
  helpful: boolean | null;
188
188
  metadata: Record<string, unknown>;
189
+ vote_count: number;
190
+ user_has_voted: boolean;
191
+ is_own: boolean;
192
+ }
193
+ /**
194
+ * Feedback visibility setting
195
+ */
196
+ type FeedbackVisibility = 'own' | 'organization' | 'all';
197
+ /**
198
+ * Project settings for requests
199
+ */
200
+ interface RequestsSettings {
201
+ feedbackVisibility: FeedbackVisibility;
202
+ allowVoting: boolean;
203
+ allowRequestCreation: boolean;
189
204
  }
190
205
  /**
191
206
  * Options for fetching requests
@@ -221,6 +236,7 @@ interface RequestsResponse {
221
236
  offset: number;
222
237
  hasMore: boolean;
223
238
  };
239
+ settings: RequestsSettings;
224
240
  }
225
241
  /**
226
242
  * API error response
@@ -394,6 +410,108 @@ interface CensusProviderProps {
394
410
  */
395
411
  children: React.ReactNode;
396
412
  }
413
+ interface GuideStep {
414
+ id: string;
415
+ sort_order: number;
416
+ selector_strategy: SelectorStrategy;
417
+ title: string | null;
418
+ content: string | null;
419
+ tooltip_position: TooltipPosition;
420
+ actions: GuideAction[];
421
+ wait_for: WaitForType;
422
+ wait_config: Record<string, unknown>;
423
+ }
424
+ interface SelectorStrategy {
425
+ css?: string;
426
+ xpath?: string;
427
+ text?: string;
428
+ testId?: string;
429
+ }
430
+ type TooltipPosition = 'auto' | 'top' | 'bottom' | 'left' | 'right';
431
+ type WaitForType = 'click' | 'next_button' | 'delay' | 'custom';
432
+ interface GuideAction {
433
+ type: 'click' | 'input' | 'navigate' | 'custom';
434
+ config: Record<string, unknown>;
435
+ }
436
+ interface Guide {
437
+ id: string;
438
+ name: string;
439
+ slug: string;
440
+ description: string | null;
441
+ trigger_type: GuideTriggerType;
442
+ trigger_config: TriggerConfig;
443
+ theme: GuideTheme;
444
+ allow_skip: boolean;
445
+ show_progress: boolean;
446
+ guide_steps: GuideStep[];
447
+ }
448
+ type GuideTriggerType = 'manual' | 'url_match' | 'first_visit' | 'event';
449
+ interface TriggerConfig {
450
+ url_pattern?: string;
451
+ event_name?: string;
452
+ delay_ms?: number;
453
+ }
454
+ interface GuideTheme {
455
+ primaryColor?: string;
456
+ backgroundColor?: string;
457
+ textColor?: string;
458
+ borderRadius?: string;
459
+ fontFamily?: string;
460
+ }
461
+ interface GuidesResponse {
462
+ guides: Guide[];
463
+ completedGuides: string[];
464
+ }
465
+ type GuideEventType = 'started' | 'step_viewed' | 'step_completed' | 'completed' | 'skipped' | 'dismissed';
466
+ /**
467
+ * A feature within a feature group
468
+ */
469
+ interface Feature {
470
+ id: string;
471
+ name: string;
472
+ slug: string;
473
+ description: string | null;
474
+ status: string;
475
+ article_count: number;
476
+ }
477
+ /**
478
+ * A group of related features
479
+ */
480
+ interface FeatureGroup {
481
+ id: string;
482
+ name: string;
483
+ slug: string;
484
+ description: string | null;
485
+ color: string | null;
486
+ features: Feature[];
487
+ feature_count: number;
488
+ article_count: number;
489
+ }
490
+ /**
491
+ * Response from feature groups endpoint
492
+ */
493
+ interface FeatureGroupsResponse {
494
+ feature_groups: FeatureGroup[];
495
+ }
496
+ interface GuideAnalyticsEvent {
497
+ guideId: string;
498
+ eventType: GuideEventType;
499
+ stepId?: string;
500
+ stepIndex?: number;
501
+ pageUrl?: string;
502
+ sessionId: string;
503
+ userId?: string;
504
+ metadata?: Record<string, unknown>;
505
+ }
506
+ interface TooltipOptions {
507
+ position?: TooltipPosition;
508
+ showProgress?: boolean;
509
+ showSkip?: boolean;
510
+ onNext?: () => void;
511
+ onPrev?: () => void;
512
+ onSkip?: () => void;
513
+ onClose?: () => void;
514
+ }
397
515
 
398
516
  /**
399
517
  * Census SDK Client
@@ -505,6 +623,21 @@ declare class CensusClient {
505
623
  * ```
506
624
  */
507
625
  getArticle(slugOrId: string): Promise<Article | null>;
626
+ /**
627
+ * Fetch feature groups with their features and article counts.
628
+ * Used for navigation in the knowledge base.
629
+ *
630
+ * @returns Feature groups with nested features
631
+ *
632
+ * @example
633
+ * ```typescript
634
+ * const { feature_groups } = await census.getFeatureGroups();
635
+ * feature_groups.forEach(group => {
636
+ * console.log(group.name, group.features.length);
637
+ * });
638
+ * ```
639
+ */
640
+ getFeatureGroups(): Promise<FeatureGroupsResponse>;
508
641
  /**
509
642
  * Fetch the current user's submitted requests (feedback, bugs, feature requests).
510
643
  * Requires a user to be identified first.
@@ -525,6 +658,29 @@ declare class CensusClient {
525
658
  * ```
526
659
  */
527
660
  getRequests(options?: RequestsOptions): Promise<RequestsResponse>;
661
+ /**
662
+ * Vote on a feedback request (toggle).
663
+ * If the user has already voted, removes the vote.
664
+ * If the user hasn't voted, adds a vote.
665
+ *
666
+ * @param feedbackId - ID of the feedback to vote on
667
+ * @returns Vote result with action taken and new vote count
668
+ *
669
+ * @example
670
+ * ```typescript
671
+ * // Vote on a feedback request
672
+ * const result = await census.vote('feedback-id-123');
673
+ * console.log(result.action); // 'added' or 'removed'
674
+ * console.log(result.vote_count); // 5
675
+ * console.log(result.user_has_voted); // true
676
+ * ```
677
+ */
678
+ vote(feedbackId: string): Promise<{
679
+ success: boolean;
680
+ action: 'added' | 'removed';
681
+ vote_count: number;
682
+ user_has_voted: boolean;
683
+ }>;
528
684
  /**
529
685
  * Track a custom analytics event.
530
686
  *
@@ -558,6 +714,64 @@ declare class CensusClient {
558
714
  * ```
559
715
  */
560
716
  trackBatch(options: BatchEventsOptions): Promise<void>;
717
+ /**
718
+ * Fetch available guides for the current user.
719
+ * Returns guides that match the user's context and haven't been completed.
720
+ *
721
+ * @returns Guides and list of completed guide IDs
722
+ *
723
+ * @example
724
+ * ```typescript
725
+ * const { guides, completedGuides } = await census.getGuides();
726
+ * guides.forEach(guide => console.log(guide.name));
727
+ * ```
728
+ */
729
+ getGuides(): Promise<GuidesResponse>;
730
+ /**
731
+ * Fetch a single guide by slug or ID.
732
+ *
733
+ * @param slugOrId - Guide slug or ID
734
+ * @returns Guide or null if not found
735
+ *
736
+ * @example
737
+ * ```typescript
738
+ * const guide = await census.getGuide('onboarding-tour');
739
+ * if (guide) {
740
+ * console.log(guide.name, guide.guide_steps.length);
741
+ * }
742
+ * ```
743
+ */
744
+ getGuide(slugOrId: string): Promise<Guide | null>;
745
+ /**
746
+ * Track a guide analytics event.
747
+ * Used to track user progress through guides.
748
+ *
749
+ * @param event - Guide analytics event
750
+ *
751
+ * @example
752
+ * ```typescript
753
+ * await census.trackGuideEvent({
754
+ * guideId: 'guide_123',
755
+ * eventType: 'step_completed',
756
+ * stepId: 'step_456',
757
+ * stepIndex: 2,
758
+ * sessionId: 'session_789',
759
+ * });
760
+ * ```
761
+ */
762
+ trackGuideEvent(event: GuideAnalyticsEvent): Promise<void>;
763
+ /**
764
+ * Mark a guide as completed for the current user.
765
+ * Prevents the guide from showing again.
766
+ *
767
+ * @param guideId - ID of the guide to mark as completed
768
+ *
769
+ * @example
770
+ * ```typescript
771
+ * await census.markGuideCompleted('guide_123');
772
+ * ```
773
+ */
774
+ markGuideCompleted(guideId: string): Promise<void>;
561
775
  /**
562
776
  * Get the current identified user ID
563
777
  */
@@ -593,4 +807,4 @@ declare class CensusClient {
593
807
  */
594
808
  declare function createCensus(config: CensusConfig): CensusClient;
595
809
 
596
- export { type Article, type ArticlesOptions, type ArticlesResponse, type BatchEventsOptions, CensusClient, type CensusConfig, type CensusError, type CensusProviderProps, type CensusTheme, type FeedbackButtonProps, type FeedbackOptions, type FeedbackType, type KnowledgeBaseProps, type Position, type Request, type RequestsOptions, type RequestsProps, type RequestsResponse, type TrackEventOptions, type UserIdentity, createCensus };
810
+ export { type Article, type ArticlesOptions, type ArticlesResponse, type BatchEventsOptions, CensusClient, type CensusConfig, type CensusError, type CensusProviderProps, type CensusTheme, type FeedbackButtonProps, type FeedbackOptions, type FeedbackType, type Guide, type GuideAction, type GuideAnalyticsEvent, type GuideEventType, type GuideStep, type GuideTheme, type GuideTriggerType, type GuidesResponse, type KnowledgeBaseProps, type Position, type Request, type RequestsOptions, type RequestsProps, type RequestsResponse, type SelectorStrategy, type TooltipOptions, type TooltipPosition, type TrackEventOptions, type TriggerConfig, type UserIdentity, type WaitForType, createCensus };
package/dist/index.d.ts CHANGED
@@ -186,6 +186,21 @@ interface Request {
186
186
  rating: number | null;
187
187
  helpful: boolean | null;
188
188
  metadata: Record<string, unknown>;
189
+ vote_count: number;
190
+ user_has_voted: boolean;
191
+ is_own: boolean;
192
+ }
193
+ /**
194
+ * Feedback visibility setting
195
+ */
196
+ type FeedbackVisibility = 'own' | 'organization' | 'all';
197
+ /**
198
+ * Project settings for requests
199
+ */
200
+ interface RequestsSettings {
201
+ feedbackVisibility: FeedbackVisibility;
202
+ allowVoting: boolean;
203
+ allowRequestCreation: boolean;
189
204
  }
190
205
  /**
191
206
  * Options for fetching requests
@@ -221,6 +236,7 @@ interface RequestsResponse {
221
236
  offset: number;
222
237
  hasMore: boolean;
223
238
  };
239
+ settings: RequestsSettings;
224
240
  }
225
241
  /**
226
242
  * API error response
@@ -394,6 +410,108 @@ interface CensusProviderProps {
394
410
  */
395
411
  children: React.ReactNode;
396
412
  }
413
+ interface GuideStep {
414
+ id: string;
415
+ sort_order: number;
416
+ selector_strategy: SelectorStrategy;
417
+ title: string | null;
418
+ content: string | null;
419
+ tooltip_position: TooltipPosition;
420
+ actions: GuideAction[];
421
+ wait_for: WaitForType;
422
+ wait_config: Record<string, unknown>;
423
+ }
424
+ interface SelectorStrategy {
425
+ css?: string;
426
+ xpath?: string;
427
+ text?: string;
428
+ testId?: string;
429
+ }
430
+ type TooltipPosition = 'auto' | 'top' | 'bottom' | 'left' | 'right';
431
+ type WaitForType = 'click' | 'next_button' | 'delay' | 'custom';
432
+ interface GuideAction {
433
+ type: 'click' | 'input' | 'navigate' | 'custom';
434
+ config: Record<string, unknown>;
435
+ }
436
+ interface Guide {
437
+ id: string;
438
+ name: string;
439
+ slug: string;
440
+ description: string | null;
441
+ trigger_type: GuideTriggerType;
442
+ trigger_config: TriggerConfig;
443
+ theme: GuideTheme;
444
+ allow_skip: boolean;
445
+ show_progress: boolean;
446
+ guide_steps: GuideStep[];
447
+ }
448
+ type GuideTriggerType = 'manual' | 'url_match' | 'first_visit' | 'event';
449
+ interface TriggerConfig {
450
+ url_pattern?: string;
451
+ event_name?: string;
452
+ delay_ms?: number;
453
+ }
454
+ interface GuideTheme {
455
+ primaryColor?: string;
456
+ backgroundColor?: string;
457
+ textColor?: string;
458
+ borderRadius?: string;
459
+ fontFamily?: string;
460
+ }
461
+ interface GuidesResponse {
462
+ guides: Guide[];
463
+ completedGuides: string[];
464
+ }
465
+ type GuideEventType = 'started' | 'step_viewed' | 'step_completed' | 'completed' | 'skipped' | 'dismissed';
466
+ /**
467
+ * A feature within a feature group
468
+ */
469
+ interface Feature {
470
+ id: string;
471
+ name: string;
472
+ slug: string;
473
+ description: string | null;
474
+ status: string;
475
+ article_count: number;
476
+ }
477
+ /**
478
+ * A group of related features
479
+ */
480
+ interface FeatureGroup {
481
+ id: string;
482
+ name: string;
483
+ slug: string;
484
+ description: string | null;
485
+ color: string | null;
486
+ features: Feature[];
487
+ feature_count: number;
488
+ article_count: number;
489
+ }
490
+ /**
491
+ * Response from feature groups endpoint
492
+ */
493
+ interface FeatureGroupsResponse {
494
+ feature_groups: FeatureGroup[];
495
+ }
496
+ interface GuideAnalyticsEvent {
497
+ guideId: string;
498
+ eventType: GuideEventType;
499
+ stepId?: string;
500
+ stepIndex?: number;
501
+ pageUrl?: string;
502
+ sessionId: string;
503
+ userId?: string;
504
+ metadata?: Record<string, unknown>;
505
+ }
506
+ interface TooltipOptions {
507
+ position?: TooltipPosition;
508
+ showProgress?: boolean;
509
+ showSkip?: boolean;
510
+ onNext?: () => void;
511
+ onPrev?: () => void;
512
+ onSkip?: () => void;
513
+ onClose?: () => void;
514
+ }
397
515
 
398
516
  /**
399
517
  * Census SDK Client
@@ -505,6 +623,21 @@ declare class CensusClient {
505
623
  * ```
506
624
  */
507
625
  getArticle(slugOrId: string): Promise<Article | null>;
626
+ /**
627
+ * Fetch feature groups with their features and article counts.
628
+ * Used for navigation in the knowledge base.
629
+ *
630
+ * @returns Feature groups with nested features
631
+ *
632
+ * @example
633
+ * ```typescript
634
+ * const { feature_groups } = await census.getFeatureGroups();
635
+ * feature_groups.forEach(group => {
636
+ * console.log(group.name, group.features.length);
637
+ * });
638
+ * ```
639
+ */
640
+ getFeatureGroups(): Promise<FeatureGroupsResponse>;
508
641
  /**
509
642
  * Fetch the current user's submitted requests (feedback, bugs, feature requests).
510
643
  * Requires a user to be identified first.
@@ -525,6 +658,29 @@ declare class CensusClient {
525
658
  * ```
526
659
  */
527
660
  getRequests(options?: RequestsOptions): Promise<RequestsResponse>;
661
+ /**
662
+ * Vote on a feedback request (toggle).
663
+ * If the user has already voted, removes the vote.
664
+ * If the user hasn't voted, adds a vote.
665
+ *
666
+ * @param feedbackId - ID of the feedback to vote on
667
+ * @returns Vote result with action taken and new vote count
668
+ *
669
+ * @example
670
+ * ```typescript
671
+ * // Vote on a feedback request
672
+ * const result = await census.vote('feedback-id-123');
673
+ * console.log(result.action); // 'added' or 'removed'
674
+ * console.log(result.vote_count); // 5
675
+ * console.log(result.user_has_voted); // true
676
+ * ```
677
+ */
678
+ vote(feedbackId: string): Promise<{
679
+ success: boolean;
680
+ action: 'added' | 'removed';
681
+ vote_count: number;
682
+ user_has_voted: boolean;
683
+ }>;
528
684
  /**
529
685
  * Track a custom analytics event.
530
686
  *
@@ -558,6 +714,64 @@ declare class CensusClient {
558
714
  * ```
559
715
  */
560
716
  trackBatch(options: BatchEventsOptions): Promise<void>;
717
+ /**
718
+ * Fetch available guides for the current user.
719
+ * Returns guides that match the user's context and haven't been completed.
720
+ *
721
+ * @returns Guides and list of completed guide IDs
722
+ *
723
+ * @example
724
+ * ```typescript
725
+ * const { guides, completedGuides } = await census.getGuides();
726
+ * guides.forEach(guide => console.log(guide.name));
727
+ * ```
728
+ */
729
+ getGuides(): Promise<GuidesResponse>;
730
+ /**
731
+ * Fetch a single guide by slug or ID.
732
+ *
733
+ * @param slugOrId - Guide slug or ID
734
+ * @returns Guide or null if not found
735
+ *
736
+ * @example
737
+ * ```typescript
738
+ * const guide = await census.getGuide('onboarding-tour');
739
+ * if (guide) {
740
+ * console.log(guide.name, guide.guide_steps.length);
741
+ * }
742
+ * ```
743
+ */
744
+ getGuide(slugOrId: string): Promise<Guide | null>;
745
+ /**
746
+ * Track a guide analytics event.
747
+ * Used to track user progress through guides.
748
+ *
749
+ * @param event - Guide analytics event
750
+ *
751
+ * @example
752
+ * ```typescript
753
+ * await census.trackGuideEvent({
754
+ * guideId: 'guide_123',
755
+ * eventType: 'step_completed',
756
+ * stepId: 'step_456',
757
+ * stepIndex: 2,
758
+ * sessionId: 'session_789',
759
+ * });
760
+ * ```
761
+ */
762
+ trackGuideEvent(event: GuideAnalyticsEvent): Promise<void>;
763
+ /**
764
+ * Mark a guide as completed for the current user.
765
+ * Prevents the guide from showing again.
766
+ *
767
+ * @param guideId - ID of the guide to mark as completed
768
+ *
769
+ * @example
770
+ * ```typescript
771
+ * await census.markGuideCompleted('guide_123');
772
+ * ```
773
+ */
774
+ markGuideCompleted(guideId: string): Promise<void>;
561
775
  /**
562
776
  * Get the current identified user ID
563
777
  */
@@ -593,4 +807,4 @@ declare class CensusClient {
593
807
  */
594
808
  declare function createCensus(config: CensusConfig): CensusClient;
595
809
 
596
- export { type Article, type ArticlesOptions, type ArticlesResponse, type BatchEventsOptions, CensusClient, type CensusConfig, type CensusError, type CensusProviderProps, type CensusTheme, type FeedbackButtonProps, type FeedbackOptions, type FeedbackType, type KnowledgeBaseProps, type Position, type Request, type RequestsOptions, type RequestsProps, type RequestsResponse, type TrackEventOptions, type UserIdentity, createCensus };
810
+ export { type Article, type ArticlesOptions, type ArticlesResponse, type BatchEventsOptions, CensusClient, type CensusConfig, type CensusError, type CensusProviderProps, type CensusTheme, type FeedbackButtonProps, type FeedbackOptions, type FeedbackType, type Guide, type GuideAction, type GuideAnalyticsEvent, type GuideEventType, type GuideStep, type GuideTheme, type GuideTriggerType, type GuidesResponse, type KnowledgeBaseProps, type Position, type Request, type RequestsOptions, type RequestsProps, type RequestsResponse, type SelectorStrategy, type TooltipOptions, type TooltipPosition, type TrackEventOptions, type TriggerConfig, type UserIdentity, type WaitForType, createCensus };