TaskOnEmbed Class
TaskOnEmbed is the core class of the SDK used to embed TaskOn into third-party sites and communicate with the iframe via a message bridge.
Constructor
new TaskOnEmbed(config: TaskOnEmbedConfig)Parameters
config: TaskOnEmbedConfig- configuration object
Example
import { TaskOnEmbed } from "@taskon/embed";
const embed = new TaskOnEmbed({
baseUrl: "https://taskon.xyz", // or your white-label domain
containerElement: "#taskon-container",
width: "100%",
height: "100%",
});
// Initialize the iframe
await embed.init();2
3
4
5
6
7
8
9
10
11
Properties
initialized
Read-only property indicating whether the embed has been initialized.
get initialized(): booleanExample
if (embed.initialized) {
console.log("Embed is ready to use");
}2
3
currentRoute
Get current iframe route.
get currentRoute(): stringExample
console.log("Current route:", embed.currentRoute);Methods
init()
Initialize the embed iframe and establish communication.
init(): Promise<void>Example
await embed.init();login()
Request login inside the iframe. Supports both Email and EVM wallet authentication. Can be called when already logged in to switch accounts. Duplicate login with same account will be ignored.
login(request: LoginParams): Promise<void>Parameters
request: LoginParams
Email login example
// Check if authorization is needed first
const isAuthorized = await embed.isAuthorized("Email", "user@example.com");
if (!isAuthorized) {
// First time login - signature required
await embed.login({
type: "Email",
account: "user@example.com",
signature: serverSignature, // generated by your backend
timestamp: Date.now(),
});
} else {
// Already authorized - no signature needed
await embed.login({
type: "Email",
account: "user@example.com",
});
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
EVM wallet login example
const isAuthorized = await embed.isAuthorized("WalletAddress", "0x1234...");
if (!isAuthorized) {
await embed.login({
type: "WalletAddress",
account: "0x1234...",
signature: serverSignature,
timestamp: Date.now(),
provider: window.ethereum, // Required for wallet operations
});
} else {
await embed.login({
type: "WalletAddress",
account: "0x1234...",
provider: window.ethereum,
});
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Cross-account login example
// Switch directly from userA to userB without logout
await embed.login({
type: "Email",
account: "userB@example.com",
signature: userBSignature, // Required if userB not authorized yet
timestamp: userBTimestamp,
});2
3
4
5
6
7
logout()
Request logout from current session with optional authorization cache control.
logout(options?: LogoutOptions): Promise<void>Parameters
options?: LogoutOptions- Optional logout configurationclearAuth?: boolean- Whether to clear authorization cache (default: false)false: Keep auth cache for quick re-login (recommended for account switching)true: Complete logout, clear all authorization cache (use for security-sensitive logout)
Examples
// Standard logout - keeps auth cache (recommended)
await embed.logout();;
// Complete logout - clears all authorization (use sparingly)
await embed.logout({ clearAuth: true });
### isAuthorized()
Check if the specified account has valid authorization cache. If true, login() can be called without signature/timestamp.
```typescript
isAuthorized(authType: AuthType, account: string): Promise<boolean>2
3
4
5
6
7
8
9
10
11
12
Parameters
authType: AuthType- Authentication type ("Email" or "WalletAddress")account: string- Account identifier (email address or wallet address)
Returns
Promise<boolean>- true if account has valid authorization cache, false if signature is required
Example
const isAuthorized = await embed.isAuthorized("Email", "user@example.com");
if (isAuthorized) {
// No signature needed
await embed.login({
type: "Email",
account: "user@example.com",
});
} else {
// Signature required
const { signature, timestamp } = await getServerSignature("user@example.com");
await embed.login({
type: "Email",
account: "user@example.com",
signature,
timestamp,
});
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
updateSize()
Update iframe size.
updateSize(width?: string | number, height?: string | number): voidExample
embed.updateSize("100%", 720);destroy()
Destroy the instance and release resources.
destroy(): voidExample
embed.destroy();setRoute()
Set iframe internal route.
setRoute(fullPath: string): Promise<void>Example
await embed.setRoute("/profile");setLanguage()
Set the language for the iframe interface. The iframe will switch to the specified language immediately.
setLanguage(language: string): Promise<void>Parameters
language: string- Language key (e.g., 'en', 'ko', 'ru', 'es', 'ja'). Fallback to 'en' if not supported.
Examples
// Switch to Korean
await embed.setLanguage("ko");
// Switch to Japanese
await embed.setLanguage("ja");
// Switch to Spanish
await embed.setLanguage("es");
// Unsupported language will fallback to English
await embed.setLanguage("fr"); // Falls back to 'en'2
3
4
5
6
7
8
9
10
11
Supported Languages:
en- Englishko- Korean (한국어)ja- Japanese (日本語)ru- Russian (Русский)es- Spanish (Español)
Events
Register events via embed.on(event, handler).
Available Events
loginRequired:() => void- Fired when iframe requires user authenticationrouteChanged:(fullPath: string) => void- Fired when iframe internal route changestaskCompleted:(data: TaskCompletedData) => void- Fired when user completes a taskbindConflict:(data: BindConflictData) => void- Fired when binding SNS or address fails because the account is already bound to another email
Event Examples
// Triggered when iframe needs user authentication
embed.on("loginRequired", () => {
console.log("User authentication required");
// Implement your authentication flow:
// 1. Show login modal/form
// 2. Get user credentials
// 3. Generate signature on server
// 4. Call embed.login() with signature
});
// Triggered when iframe internal route changes
embed.on("routeChanged", fullPath => {
console.log("Internal route changed to:", fullPath);
// Optional: Sync with external URL routing
// window.history.replaceState(null, '', `/embed${fullPath}`);
});
// Triggered when user completes a task
embed.on("taskCompleted", data => {
console.log("Task completed:", data);
// Task completion data includes:
console.log("Task ID:", data.taskId);
console.log("Task Name:", data.taskName);
console.log("Template ID:", data.templateId);
console.log("Rewards:", data.rewards);
// Handle task completion (analytics, notifications, etc.)
analytics.track("task_completed", {
task_id: data.taskId,
task_name: data.taskName,
rewards: data.rewards,
});
});
// Triggered when binding SNS or address fails due to account conflict
// (White-label mode only)
embed.on("bindConflict", data => {
console.log("Bind conflict detected:", data);
// Bind conflict data includes:
console.log("Already bound to email:", data.email);
console.log("Bind type:", data.bindType); // "sns" or "address"
if (data.bindType === "sns") {
console.log("SNS type:", data.snsType); // e.g., "twitter", "discord"
// Handle SNS binding conflict
showNotification(
`This ${data.snsType} account is already bound to ${data.email}. ` +
`Please use a different ${data.snsType} account or contact support.`
);
} else if (data.bindType === "address") {
console.log("Address:", data.address);
// Handle wallet address binding conflict
showNotification(
`This wallet address is already bound to ${data.email}. ` +
`Please use a different wallet or contact support.`
);
}
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
TaskCompletedData Interface
interface TaskCompletedData {
/** Task identifier */
taskId: string;
/** Task name/title */
taskName: string;
/** Task template identifier */
templateId: string;
/** The rewards of the task */
rewards: TaskReward[];
}
interface TaskReward {
/** Type of reward */
rewardType: "Token" | "GTCPoints";
/** Amount of reward */
rewardAmount: string;
/** Name of points/token (optional) */
pointName?: string;
/** Human readable reward description */
rewardDescription: string;
/** Token contract address (if applicable) */
tokenAddress?: string;
/** Blockchain network (if applicable) */
tokenNetwork?: string;
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
BindConflictData Interface
interface BindConflictData {
/** Email that the SNS or address is already bound to */
email: string;
/** Type of binding that failed */
bindType: "sns" | "address";
/** SNS type if bindType is "sns" */
snsType?: SnsType;
/** Address if bindType is "address" */
address?: string;
}
type SnsType = "twitter" | "discord" | "telegram" | "reddit";2
3
4
5
6
7
8
9
10
11
12
Complete Example
import { TaskOnEmbed } from "@taskon/embed";
const embed = new TaskOnEmbed({
baseUrl: "https://taskon.xyz",
containerElement: "#taskon-container",
language: "en", // Initial language
width: "100%",
height: 600,
});
// Initialize the embed
await embed.init();
// Set up event listeners
embed.on("loginRequired", async () => {
// Handle email login
const email = "user@example.com";
const isAuthorized = await embed.isAuthorized("Email", email);
if (!isAuthorized) {
const { signature, timestamp } = await fetch("/api/auth/sign", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ account: email }),
}).then(r => r.json());
await embed.login({
type: "Email",
account: email,
signature,
timestamp,
});
} else {
await embed.login({
type: "Email",
account: email,
});
}
});
embed.on("routeChanged", fullPath => {
console.log("Route changed to:", fullPath);
});
embed.on("taskCompleted", data => {
console.log("Task completed:", data);
// Analytics tracking
analytics.track("task_completed", {
task_id: data.taskId,
task_name: data.taskName,
rewards: data.rewards,
});
// Show success notification
showNotification(`Congratulations! You completed "${data.taskName}"`);
});
embed.on("bindConflict", data => {
// Handle binding conflicts
const message =
data.bindType === "sns"
? `This ${data.snsType} account is already linked to ${data.email}`
: `This wallet address is already linked to ${data.email}`;
showNotification(message, "error");
});
// Language switching example
const languageSelector = document.getElementById("language-selector");
languageSelector?.addEventListener("change", async event => {
const selectedLanguage = (event.target as HTMLSelectElement).value;
await embed.setLanguage(selectedLanguage);
console.log(`Language switched to: ${selectedLanguage}`);
});
// Route navigation example
const navigateToProfile = () => {
embed.setRoute("/profile");
};
// Dynamic size adjustment
const resizeEmbed = (width: string | number, height: string | number) => {
embed.updateSize(width, height);
};2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85