Package Exports
- @spektra-cloudevents/zoho-asap-widget
- @spektra-cloudevents/zoho-asap-widget/package.json
Readme
Zoho Desk ASAP Widget - Standalone Angular Library
A completely standalone Angular library (10+) that wraps the Zoho Desk ASAP 2.0 widget. This library handles everything internally: authentication, session management, and storage clearing. Your app only needs to pass a JWT token - no Zoho-specific code required.
๐ฏ Key Features
- โ Truly Standalone: Accepts JWT token, handles authentication internally
- โ Zero Zoho Dependencies in App: No AsapService, no additional authentication code needed
- โ Multi-User Safe: Automatically detects user changes and clears sessions
- โ Smart Token Refresh: Distinguishes token refresh (same user) from user switch (different user)
- โ Automatic Session Management: Clears localStorage, sessionStorage, and cookies on logout
- โ Prefill Support: Automatic form prefilling with dynamic values
- โ Angular 10-18+ Compatible: Works with all modern Angular versions
- โ Production Ready: Clean code, no console logs, robust error handling
๐ฆ Installation
npm install @cloudlabs/zoho-asap-widgetImport the module in your app:
import { ZohoAsapWidgetModule } from '@cloudlabs/zoho-asap-widget';
@NgModule({
imports: [ZohoAsapWidgetModule],
// ...
})
export class AppModule { }๐ Basic Usage
Prerequisites: Your app must have a JWT token for authenticating users with Zoho Desk ASAP.
<!-- Simply pass your JWT token to the widget -->
<zoho-asap-widget
*ngIf="jwtToken"
[appId]="'YOUR_ZOHO_APP_ID'"
[orgId]="'YOUR_ZOHO_ORG_ID'"
[jwtToken]="jwtToken"
[enabled]="true">
</zoho-asap-widget>That's it! The widget handles:
- User authentication with Zoho
- Session management
- Storage cleanup on logout
- User switching detection
With Form Prefill
<zoho-asap-widget
*ngIf="jwtToken"
[appId]="'YOUR_ZOHO_APP_ID'"
[orgId]="'YOUR_ZOHO_ORG_ID'"
[jwtToken]="jwtToken"
[enabled]="true"
[prefillFields]="prefillData"
[departmentId]="'YOUR_DEPT_ID'"
[layoutId]="'YOUR_LAYOUT_ID'">
</zoho-asap-widget>Where prefillData is an object in your component:
prefillData: any = {
subject: 'Support Request', // Standard Zoho field
cf_event_request_id: 'MS012345678910', // Custom field
};Dynamic prefill example:
// Set subject dynamically with user name
this.prefillData.subject = `Support Request from ${this.userDisplayName}`;
// Update prefill based on user context
if (isPremiumUser) {
this.prefillData = {
subject: `Priority Support - ${userName}`,
cf_priority: 'High',
cf_user_type: 'Premium'
};
}๐ง Component Inputs
interface ZohoAsapWidgetInputs {
// Required
appId: string; // Zoho ASAP application ID
orgId: string; // Zoho organization ID
jwtToken: string; // JWT token for Zoho authentication
// Optional
enabled?: boolean; // Enable/disable widget (default: true)
nonce?: string; // Security nonce for script loading
// Prefill (optional)
prefillFields?: { // Object with field names and values
[fieldName: string]: any; // e.g., { cf_event_request_id: '12345', cf_priority: 'High' }
};
departmentId?: string; // Department ID (required for prefill)
layoutId?: string; // Form layout ID (required for prefill)
}๐ How It Works
Architecture
โโโโโโโโโโโโโโโโโโโ
โ Your App โ
โ (JWT Token) โ
โโโโโโโโโโฌโโโโโโโโโ
โ JWT Token
โผ
โโโโโโโโโโโโโโโโโโโ
โ Zoho Widget โ โโโบ Authenticate with JWT
โ (Library) โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ Login with JWT
โโโโโโโโโโโโโโโโโโโ
โ Zoho Desk โ
โ ASAP API โ
โโโโโโโโโโโโโโโโโโโFlow
- App authenticates user and obtains JWT token
- App passes JWT token to widget via
[jwtToken]input - Widget handles everything:
- Logs into Zoho Desk ASAP with JWT token
- Manages session lifecycle
- On logout: Widget clears all Zoho storage/cookies automatically
๐ง Smart User Detection
The widget intelligently handles two scenarios:
Scenario 1: Same User, Token Refresh
// User's JWT token expires and gets refreshed
// Old: eyJhbGc...user@example.com...abc
// New: eyJhbGc...user@example.com...xyz
// Widget: Extracts user identity (email/oid)
// โ Same user detected
// โ Updates JWT without logout
// โ User keeps their session stateScenario 2: Different User Login
// User A logs out, User B logs in
// Old: eyJhbGc...userA@example.com...
// New: eyJhbGc...userB@example.com...
// Widget: Extracts user identity
// โ Different user detected
// โ Fully logs out User A
// โ Clears all storage/cookies
// โ Logs in User B with clean sessionThis prevents unnecessary session disruption while ensuring complete isolation between users.
## ๐งน Session Management (Automatic)
The widget handles **everything automatically** when component lifecycle changes:
```typescript
// When widget is destroyed (*ngIf becomes false):
// - Detects ngOnDestroy
// - Calls Zoho logout
// - Clears ALL Zoho storage (localStorage, sessionStorage, cookies)
// - Waits for logout confirmation event
// When widget is created fresh (*ngIf becomes true):
// - Clears any residual Zoho storage (safety check)
// - Loads Zoho script
// - Logs into Zoho with JWT token
// - Establishes fresh sessionYour app just controls the *ngIf condition - widget does the rest!
๐ Multi-User Scenarios
Perfect for applications where users switch accounts:
// User A logged in
this.jwtToken = 'eyJhbGc...userA@example.com...';
// Widget: Logs in User A
// User A logs out
this.jwtToken = null;
// Widget: Detects token removal, logs out, clears all Zoho data
// User B logs in (component recreated)
this.jwtToken = 'eyJhbGc...userB@example.com...';
// Widget: Fresh component โ clears storage โ new session
// User B sees ONLY their data, never User A's๐ Form Prefilling
To prefill ticket fields when opening the widget, pass an object with field names and values:
<zoho-asap-widget
[appId]="'202588000344171472'"
[orgId]="'649984843'"
[jwtToken]="jwtToken"
[prefillFields]="{
subject: 'Technical Support Request', // Standard field
description: 'Issue details here', // Standard field
cf_event_request_id: 'EVENT-12345', // Custom field
cf_priority: 'High', // Custom field
cf_category: 'Technical Issue', // Custom field
cf_user_email: userEmail, // Custom field with dynamic value
cf_location: 'Building A' // Custom field
}"
[departmentId]="'202588000019741045'"
[layoutId]="'202588000019743298'">
</zoho-asap-widget>Field Types:
Standard Zoho Fields (no prefix needed):
subject- Ticket subject/titledescription- Ticket description/bodyemail- Contact emailphone- Contact phone
Custom Fields (require cf_ prefix):
cf_event_request_id- Your custom event ID fieldcf_priority- Your custom priority fieldcf_category- Your custom category fieldcf_*- Any other custom field you've created
Requirements:
prefillFields: Object where keys are field names (standard or custom)departmentId: Zoho department ID (required for prefill)layoutId: Zoho form layout ID (required for prefill)
How to find field API names:
- Go to Zoho Desk > Setup > Channels > ASAP
- Click on your department's form layout
- Standard fields: Use lowercase names (
subject,description,email) - Custom fields: Will have API names like
cf_event_request_id,cf_priority
Dynamic prefill with user context:
// Construct prefill data with user information
prefillData = {
subject: `Support Request from ${userName}`,
email: userEmail,
cf_event_request_id: ticketId,
cf_user_type: userType,
cf_priority: priority
};
// Update specific fields dynamically
this.prefillData.cf_event_request_id = newTicketId;
this.prefillData.subject = `Updated Request - ${newTicketId}`;
// Widget automatically reloads when prefillFields object reference changes
this.prefillData = { ...this.prefillData };The widget automatically:
- Configures prefill before loading the Zoho script
- Reapplies prefill after user login
- Reloads widget when
prefillFieldsobject changes
Important: What Your App Needs vs. Doesn't Need
โ Your App Needs to Provide
JWT Token - For Zoho Desk ASAP authentication
- Get this from your authentication service/backend
- Pass it to the widget:
[jwtToken]="yourToken"
Zoho Configuration - Your Zoho Desk ASAP credentials
appId: From Zoho Desk ASAP setuporgId: Your Zoho organization ID
Optional: Prefill Data - Custom field values for ticket forms
prefillFields: Object with field names and valuesdepartmentId&layoutId: Required if using prefill
โ Your App Does NOT Need
Any Zoho-specific services or logicAdditional authentication code (widget handles JWT authentication)Session management codeStorage/cookie clearing logicLogout/login event handlersUser switching detectionImport anything exceptZohoAsapWidgetModule
Summary: Just provide the JWT token and Zoho config - the widget handles all authentication and session management internally!
๐๏ธ Building & Publishing
# Build the library for production
ng build zoho-asap-widget --configuration production
# Navigate to dist folder
cd dist/zoho-asap-widget
# Publish to npm (one-time login: npm login)
npm publish --access public
# For updates, increment version first:
# npm version patch # 1.0.0 -> 1.0.1
# npm version minor # 1.0.0 -> 1.1.0
# npm version major # 1.0.0 -> 2.0.0๐ Troubleshooting
Widget shows old user's data after login
- Cause: Browser cache not cleared
- Solution: Widget now clears storage on
ngOnInit()automatically - Manual fix: Clear browser cache (Ctrl+Shift+Delete โ All time)
Widget not loading
- Check:
appIdandorgIdare correct - Check: JWT token is valid (not null/undefined)
- Check: Network connectivity to Zoho services
Token refresh causes logout
- Cause: Should not happen - widget detects same user
- Debug: Check console for user identity extraction logs
- Verify: JWT payload has
oid,sub, oremailclaim
๐ Resources
๐ License
MIT