Vanilla JavaScript / Standalone SDK
Use the TagadaPay SDK in any JavaScript project - no framework required!
Perfect for:
Pure HTML/CSS/JS sites
Server-rendered apps
Other frameworks (Svelte, Angular, Vue, etc.)
WordPress, Shopify, or any platform
Quick Start
Installation
npm install @tagadapay/plugin-sdk
Basic Usage
import { createTagadaClient , FunnelActionType } from '@tagadapay/plugin-sdk/v2/standalone' ;
// 1. Create client - funnel auto-initializes!
const client = createTagadaClient ({
features: { funnel: true }
});
// 2. Subscribe to funnel state
client . funnel . subscribe (( funnelState ) => {
if ( funnelState . isInitialized && funnelState . context ) {
console . log ( '✅ Funnel ready!' , funnelState . context );
// Render your UI here
}
});
// 3. Use funnel methods
document . getElementById ( 'pay-btn' ). onclick = async () => {
await client . funnel . navigate ({
type: FunnelActionType . PAYMENT_SUCCESS ,
data: {
order: { id: 'ord_123' , amount: 99.99 }
}
});
// Auto-redirects to next page!
};
That’s it! No manual initialization, no complex state management. The SDK handles everything automatically.
How It Works
The SDK automatically:
✅ Creates an anonymous session
✅ Initializes the funnel (when enabled)
✅ Loads configuration and static resources
✅ Handles navigation and redirects
All you do is:
Create the client
Subscribe to get updates
Use client.funnel.navigate() to move between steps
Complete Example
Here’s a full checkout page in vanilla JavaScript:
import { createTagadaClient , FunnelActionType } from '@tagadapay/plugin-sdk/v2/standalone' ;
// Create client
const client = createTagadaClient ({
features: { funnel: true }
});
// Subscribe to funnel ready state
client . funnel . subscribe (( funnelState ) => {
if ( funnelState . isInitialized && funnelState . context ) {
renderCheckout ( funnelState . context );
} else if ( funnelState . error ) {
showError ( funnelState . error . message );
}
});
function renderCheckout ( context ) {
// Get static resources (configured in CRM)
const offerId = context . static ?. offer ?. id ;
// Get context data (from previous steps)
const order = context . resources ?. order ;
const customer = context . resources ?. customer ;
// Render your UI
document . getElementById ( 'customer-email' ). textContent = customer ?. email || 'Guest' ;
document . getElementById ( 'order-total' ). textContent = `$ ${ order ?. amount || 0 } ` ;
// Setup payment button
document . getElementById ( 'pay-btn' ). onclick = async () => {
try {
await client . funnel . navigate ({
type: FunnelActionType . PAYMENT_SUCCESS ,
data: {
resources: {
order: {
id: 'ord_123' ,
amount: 4900 ,
currency: 'USD'
},
customer: {
email: document . getElementById ( 'email-input' ). value
}
}
}
});
// Automatically redirects to thank you page!
} catch ( error ) {
alert ( 'Payment failed: ' + error . message );
}
};
}
function showError ( message ) {
document . getElementById ( 'error' ). textContent = message ;
}
Available Methods
Client State
// Get current state
const state = client . getState ();
console . log ( state . store ); // Store info
console . log ( state . customer ); // Customer info
console . log ( state . session ); // Session info
// Subscribe to state changes
client . subscribe (( state ) => {
console . log ( 'State updated:' , state );
});
Funnel Methods
// Navigate to next step
await client . funnel . navigate ({
type: FunnelActionType . PAYMENT_SUCCESS ,
data: { /* your data */ }
});
// Update funnel context
await client . funnel . updateContext ({
metadata: {
customField: 'value'
}
});
// Get current funnel state
const funnelState = client . funnel . getState ();
console . log ( funnelState . context ); // Current funnel context
console . log ( funnelState . isLoading ); // Loading state
console . log ( funnelState . error ); // Error if any
Funnel Action Types
All available action types for funnel.navigate():
FunnelActionType . PAYMENT_SUCCESS // Payment completed
FunnelActionType . PAYMENT_FAILED // Payment failed
FunnelActionType . OFFER_ACCEPTED // Upsell accepted
FunnelActionType . OFFER_DECLINED // Upsell declined
FunnelActionType . FORM_SUBMITTED // Form completed
FunnelActionType . SKIP // Skip current step
Working with Static Resources
Static resources are configured by merchants in the CRM. Your code accesses them dynamically:
client . funnel . subscribe (( funnelState ) => {
if ( funnelState . context ) {
// Access static resources
const offerId = funnelState . context . static ?. offer ?. id ;
const productId = funnelState . context . static ?. product ?. id ;
const variantId = funnelState . context . static ?. variant ?. id ;
// Fetch the actual offer data
if ( offerId ) {
fetchOffer ( offerId ). then ( offer => {
document . getElementById ( 'offer-title' ). textContent = offer . title ;
document . getElementById ( 'offer-price' ). textContent = `$ ${ offer . price } ` ;
});
}
}
});
Local Testing
For local development, create config/resources.static.json:
{
"offer" : {
"id" : "offer_test123"
},
"product" : {
"id" : "prod_test456"
}
}
The SDK automatically loads this in local dev!
Configuration
const client = createTagadaClient ({
// Environment (auto-detected by default)
environment: 'production' , // 'local' | 'development' | 'production'
// Debug mode (auto-enabled in local dev)
debugMode: true ,
// Features
features: {
funnel: true , // Enable funnel navigation
},
// Local config name (for testing different presets)
localConfig: 'premium' , // Loads config/premium.config.json
});
Error Handling
// Funnel errors
client . funnel . subscribe (( funnelState ) => {
if ( funnelState . error ) {
console . error ( 'Funnel error:' , funnelState . error );
showErrorMessage ( funnelState . error . message );
}
if ( funnelState . sessionError ) {
console . error ( 'Session error:' , funnelState . sessionError );
// Session initialization failed
}
});
// Navigation errors
try {
await client . funnel . navigate ({
type: FunnelActionType . PAYMENT_SUCCESS ,
data: { /* ... */ }
});
} catch ( error ) {
console . error ( 'Navigation failed:' , error );
alert ( 'Failed to proceed: ' + error . message );
}
TypeScript Support
Full TypeScript support included:
import {
createTagadaClient ,
FunnelActionType ,
type TagadaState ,
type SimpleFunnelContext
} from '@tagadapay/plugin-sdk/v2/standalone' ;
const client = createTagadaClient ({
features: { funnel: true }
});
client . subscribe (( state : TagadaState ) => {
// Fully typed!
console . log ( state . store ?. id );
console . log ( state . customer ?. email );
});
client . funnel . subscribe (( funnelState ) => {
if ( funnelState . context ) {
const context : SimpleFunnelContext = funnelState . context ;
// All context properties are typed
}
});
Real-World Example: Checkout Page
<! DOCTYPE html >
< html >
< head >
< title > Checkout </ title >
</ head >
< body >
< div id = "app" >
< div id = "loading" > Loading... </ div >
< div id = "checkout" style = "display: none;" >
< h1 > Checkout </ h1 >
< div id = "order-summary" ></ div >
< input id = "email" type = "email" placeholder = "Email" />
< button id = "pay-btn" > Pay Now </ button >
</ div >
< div id = "error" ></ div >
</ div >
< script type = "module" src = "/main.js" ></ script >
</ body >
</ html >
// main.js
import { createTagadaClient , FunnelActionType } from '@tagadapay/plugin-sdk/v2/standalone' ;
const client = createTagadaClient ({
features: { funnel: true }
});
let globalOrder = null ;
// Wait for funnel ready
client . funnel . subscribe (( funnelState ) => {
if ( funnelState . isInitialized && funnelState . context ) {
document . getElementById ( 'loading' ). style . display = 'none' ;
document . getElementById ( 'checkout' ). style . display = 'block' ;
// Get order from context (if coming from previous step)
globalOrder = funnelState . context . resources ?. order || {
id: 'new-order' ,
amount: 4900 ,
currency: 'USD'
};
document . getElementById ( 'order-summary' ). innerHTML = `
<p>Total: $ ${ ( globalOrder . amount / 100 ). toFixed ( 2 ) } </p>
` ;
} else if ( funnelState . error ) {
document . getElementById ( 'loading' ). style . display = 'none' ;
document . getElementById ( 'error' ). textContent = funnelState . error . message ;
}
});
// Handle payment
document . getElementById ( 'pay-btn' ). onclick = async () => {
const email = document . getElementById ( 'email' ). value ;
if ( ! email ) {
alert ( 'Please enter your email' );
return ;
}
try {
await client . funnel . navigate ({
type: FunnelActionType . PAYMENT_SUCCESS ,
data: {
resources: {
order: {
... globalOrder ,
status: 'paid'
},
customer: {
email ,
id: `cus_ ${ Date . now () } `
}
}
}
});
// Auto-redirects to next page (upsell or thank you)
} catch ( error ) {
alert ( 'Payment failed: ' + error . message );
}
};
Comparison: Before vs After
❌ Old Way (Too Complex)
const client = createTagadaClient ({ features: { funnel: true } });
// Wait for client ready
client . subscribe ( async ( state ) => {
if ( state . isInitialized && state . auth . session && state . store ) {
// Manual funnel initialization
const context = await client . funnel . autoInitialize (
{ customerId: state . auth . session . customerId },
{ id: state . store . id , accountId: state . store . accountId }
);
// Now render UI...
}
});
✅ New Way (Simple!)
const client = createTagadaClient ({ features: { funnel: true } });
// Funnel auto-initializes - just subscribe!
client . funnel . subscribe (( funnelState ) => {
if ( funnelState . isInitialized && funnelState . context ) {
// Render UI immediately
}
});
Next Steps
Build a Funnel Follow the step-by-step tutorial
Funnel Resources Learn about passing data between steps
API Reference Explore all available methods
Examples See complete examples