Vanilla JavaScript Integration
Add analytics to your Figma plugin with the TodeClient class. This framework-agnostic guide works with vanilla JavaScript, TypeScript, or any framework not covered by our specific adapters.
Installation
Install the core SDK and vanilla adapter:
Terminal
npm install @tode-sdk/core @tode-sdk/figma-vanillaSetup
Initialize in Plugin Controller
Set up Tode in your plugin's main code file:
code.js
import { tode } from '@tode-sdk/core';
// Show your UI
figma.showUI(__html__, { width: 400, height: 600 });
// Initialize Tode for Figma plugin analytics
await tode.init({ apiKey: 'your-api-key' });
// Optional: Track plugin open from controller
tode.trackAction('plugin_opened');Configure Network Access
Add Tode's URLs to your plugin's manifest.json to enable analytics requests. Learn more about network access.
manifest.json
{
"name": "Your Plugin",
"id": "your-plugin-id",
"api": "1.0.0",
"main": "code.js",
"ui": "index.html",
"networkAccess": {
"allowedDomains": [
"https://mvp-events-processing-production.up.railway.app",
"wss://mvp-events-processing-production.up.railway.app"
]
}
}Use TodeClient in Your UI
Create a TodeClient instance in your UI code:
ui.js
import { TodeClient } from '@tode-sdk/figma-vanilla';
const client = new TodeClient();
client.on('ready', (isReady) => {
if (isReady) {
console.log('Tode ready for tracking!');
}
});
// Track button clicks
document.querySelector('#exportBtn').addEventListener('click', () => {
if (client.isReady) {
client.trackAction('export_clicked');
}
});Client Reference
Constructor
TypeScript
const client = new TodeClient();Properties
| Property | Type | Description |
|---|---|---|
isReady | boolean | Whether Tode is initialized (tode.isReady) |
tode | Tode | Direct access to Tode instance |
Methods
| Method | Description |
|---|---|
on(event, callback) | Add event listener |
off(event, callback) | Remove event listener |
trackAction(name) | Track a simple action (API) |
trackActionWithMetric(name, value) | Track action with numeric value (API) |
destroy() | Clean up all resources |
Events
| Event | Payload | Description |
|---|---|---|
ready | boolean | Fired when ready state changes |
Examples
Basic Tracking
ui.ts
import { TodeClient } from '@tode-sdk/figma-vanilla';
const client = new TodeClient();
// Track tool selection
document.querySelectorAll('.tool-btn').forEach(btn => {
btn.addEventListener('click', () => {
const tool = btn.dataset.tool;
if (client.isReady) {
client.trackAction(`tool_selected_${tool}`);
}
});
});Track with Metrics
export.js
import { TodeClient } from '@tode-sdk/figma-vanilla';
const client = new TodeClient();
async function exportItems(items) {
// Perform export logic...
// Track export with item count for Figma widget analytics
if (client.isReady) {
client.trackActionWithMetric('items_exported', items.length);
}
}Event Listeners
ui.ts
import { TodeClient } from '@tode-sdk/figma-vanilla';
const client = new TodeClient();
// Listen for ready state
client.on('ready', (isReady) => {
console.log('Ready:', isReady);
updateUI(isReady);
});
function updateUI(ready) {
document.querySelector('#status').textContent =
ready ? 'Connected' : 'Connecting...';
}Cleanup on Unload
ui.ts
import { TodeClient } from '@tode-sdk/figma-vanilla';
const client = new TodeClient();
// Clean up when window closes
window.addEventListener('beforeunload', () => {
client.destroy();
});With HTML
index.html
<!DOCTYPE html>
<html>
<head>
<title>My Figma Plugin</title>
</head>
<body>
<div id="status">Connecting...</div>
<button id="exportBtn" disabled>Export</button>
<button id="trackBtn" disabled>Track Action</button>
<script type="module">
import { TodeClient } from '@tode-sdk/figma-vanilla';
const client = new TodeClient();
const exportBtn = document.getElementById('exportBtn');
const trackBtn = document.getElementById('trackBtn');
const status = document.getElementById('status');
client.on('ready', (isReady) => {
exportBtn.disabled = !isReady;
trackBtn.disabled = !isReady;
status.textContent = isReady ? 'Ready' : 'Connecting...';
});
exportBtn.addEventListener('click', () => {
client.trackAction('export_clicked');
});
trackBtn.addEventListener('click', () => {
client.trackActionWithMetric('custom_metric', 42);
});
</script>
</body>
</html>Remove Event Listeners
ui.ts
import { TodeClient } from '@tode-sdk/figma-vanilla';
const client = new TodeClient();
const readyHandler = (isReady) => {
console.log('Ready:', isReady);
};
// Add listener
client.on('ready', readyHandler);
// Remove listener later
client.off('ready', readyHandler);Best Practices
1. Always Clean Up
Call destroy() when your plugin closes:
TypeScript
// Good - clean up resources
window.addEventListener('beforeunload', () => {
client.destroy();
});2. Check isReady Before Tracking
TypeScript
// Good
if (client.isReady) {
client.trackAction('action');
}
// Bad - might fail silently
client.trackAction('action');3. Use Event Listeners for UI Updates
TypeScript
// Good - reactive UI updates
client.on('ready', updateUI);
// Bad - polling
setInterval(() => {
updateUI(client.isReady);
}, 100);4. Use Descriptive Action Names
TypeScript
// Good - clear and descriptive
client.trackAction('export_to_png');
client.trackAction('layer_renamed');
// Bad - too vague
client.trackAction('click');
client.trackAction('action1');5. Direct Tode Access When Needed
TypeScript
// Use client methods
client.trackAction('action');
// Or access tode directly for advanced usage
client.tode.trackAction('action');Integration with Other Libraries
With jQuery
app.js
import { TodeClient } from '@tode-sdk/figma-vanilla';
const client = new TodeClient();
$(document).ready(() => {
client.on('ready', (isReady) => {
$('.track-btn').prop('disabled', !isReady);
});
$('.track-btn').on('click', function() {
const action = $(this).data('action');
client.trackAction(action);
});
});With Lit
my-element.js
import { LitElement, html } from 'lit';
import { TodeClient } from '@tode-sdk/figma-vanilla';
class MyElement extends LitElement {
client = new TodeClient();
isReady = false;
connectedCallback() {
super.connectedCallback();
this.client.on('ready', (ready) => {
this.isReady = ready;
this.requestUpdate();
});
}
disconnectedCallback() {
super.disconnectedCallback();
this.client.destroy();
}
render() {
return html`
<button
?disabled=${!this.isReady}
@click=${() => this.client.trackAction('click')}>
Track
</button>
`;
}
}Next Steps
- Learn about the API Reference for all available methods
- See framework-specific guides: React, Vue, Angular, Svelte