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-vanilla

Setup

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

PropertyTypeDescription
isReadybooleanWhether Tode is initialized (tode.isReady)
todeTodeDirect access to Tode instance

Methods

MethodDescription
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

EventPayloadDescription
readybooleanFired 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

Track your Figma plugin

Sign up to get your API key and start collecting analytics in minutes.

Get your API key