Resync JavaScript
A powerful JavaScript library for dynamic content management, remote configuration, and in-app campaign. Resync allows you to manage embed dynamic banners, ctas, forms, text, run campaigns into your mobile app. Deliver dynamic content without app updates. Works seamlessly across JavaScript, React Native, and Expo applications.
Featuresโ
- ๐ Remote Configuration - Manage app configs remotely without code deployments
- ๐งช In-app Campaigns - Run campaigns with audiences, automatic variant assignment and tracking
- ๐จ Dynamic Content Management - Fetch and render content views defined in your Resync dashboard
- ๐ Event Logging - Track custom events and user interactions
- ๐พ Smart Caching - Automatic environment-based caching (6h production, 0ms development)
- ๐ Real-time Updates - Subscribe to configuration changes with callback support
- ๐ฑ Cross-Platform - Works with vanilla JavaScript, React Native, and Expo
- ๐ง TypeScript Support - Full TypeScript definitions included
- ๐ฏ User Targeting - Set user attributes for personalized experiences and audience creation.
Installationโ
npm install resync-javascript
# or
yarn add resync-javascript
Quick Startโ
1. Initialize Resyncโ
import Resync from 'resync-javascript';
// Initialize Resync with your API credentials
await Resync.init({
key: 'your-api-key',
appId: 7,
callback: async (config) => {
console.log('Resync initialized with config:', config);
},
storage: localStorage, // or AsyncStorage for React Native
environment: 'production',
});
2. Get Remote Configurationโ
// Get a specific config value
const featureEnabled = Resync.getConfig('FEATURE_FLAG');
const apiEndpoint = Resync.getConfig('API_ENDPOINT');
console.log('Feature enabled:', featureEnabled);
3. Campaignโ
// Get variant for an Campaign experiment
const variant = await Resync.getVariant('homepage_experiment');
if (variant === 'variant_a') {
// Show variant A
} else {
// Show variant B
}
4. Event Loggingโ
// Log custom events
Resync.logEvent({
eventId: 'evt_button_clicked',
metadata: {
buttonName: 'signup',
screen: 'homepage',
},
});
5. Get Content Blocksโ
// Fetch all content views
const contentViews = Resync.getContent();
// Find a specific content view by name
const welcomeCard = contentViews.find(
(view) => view.name === 'HomeWelcomeCard'
);
console.log('Welcome card content:', welcomeCard);
API Referenceโ
Resync.init(options)โ
Initialize the Resync SDK. Must be called before using any other methods.
Parametersโ
| Parameter | Type | Required | Description |
|---|---|---|---|
key | string | โ | Your Resync API key |
appId | number | โ | Your application ID |
callback | () => void | โ | Callback function invoked when config is loaded |
storage | Storage | โ | Storage object for caching (localStorage, AsyncStorage, etc.) |
environment | sandbox | production | โ |
Returnsโ
Promise<void> - Returns the Resync instance
Exampleโ
await Resync.init({
key: 'rsk_live_abc123',
appId: 7,
callback: () => {
console.log('Config loaded:');
},
storage: localStorage,
environment: 'sandbox'
});
Resync.getConfig(key)โ
Get a configuration value by key.
Parametersโ
| Parameter | Type | Required | Description |
|---|---|---|---|
key | string | โ | Configuration key to retrieve |
Returnsโ
any - The configuration value
Exampleโ
const apiUrl = Resync.getConfig('API_BASE_URL');
const maxRetries = Resync.getConfig('MAX_RETRIES');
const features = Resync.getConfig('ENABLED_FEATURES');
console.log('API URL:', apiUrl);
console.log('Max retries:', maxRetries);
Resync.getVariant(campaignName)โ
Get the assigned variant for a Campaign.
Parametersโ
| Parameter | Type | Required | Description |
|---|---|---|---|
campaignName | string | โ | Name of the campaign |
Returnsโ
Promise<number | null> - Returns the variant content view ID or null
Exampleโ
const variant = await Resync.getVariant('checkout_flow_test');
if (variant === 123) {
// Show variant A (content view ID 123)
renderCheckoutVariantA();
} else if (variant === 124) {
// Show variant B (content view ID 124)
renderCheckoutVariantB();
}
Resync.getContent()โ
Get all content views from the current configuration.
Returnsโ
ContentView[] - Array of content views
Exampleโ
const contentViews = Resync.getContent();
// Find specific content view
const bannerContent = contentViews.find(
(view) => view.name === 'PromoAnnouncement'
);
// Iterate through all published content
contentViews
.filter((view) => view.status === 'published')
.forEach((view) => {
console.log(`Content view: ${view.name}`);
});
Resync.loginUser(userId, metadata)โ
Set the user ID for tracking and personalized variant assignment.
Parametersโ
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | number | โ | Unique user identifier |
metadata | object | โ | User metadata (email, name, phone, language) |
Returnsโ
Promise<boolean> - Returns true if successful
Exampleโ
// Simple user ID
await Resync.loginUser('user_12345');
// With metadata
await Resync.loginUser('user_12345', {
email: 'user@example.com',
name: 'John Doe',
phone: '+1234567890',
language: 'en',
});
Resync.setUserAttributes(attributes)โ
Set user attributes for targeting and personalization.
Parametersโ
| Parameter | Type | Required | Description |
|---|---|---|---|
attributes | object | โ | User attributes object |
attributes.email | string | โ | User email |
attributes.name | string | โ | User name |
attributes.phone | string | โ | User phone |
attributes.language | string | โ | User language |
attributes.attributes | object | โ | Additional custom attributes |
Returnsโ
Promise<boolean> - Returns true if successful
Exampleโ
await Resync.setUserAttributes({
email: 'user@example.com',
name: 'Jane Smith',
phone: '+1234567890',
language: 'en',
attributes: {
subscriptionTier: 'premium',
country: 'US',
signupDate: '2025-01-15',
},
});
Resync.setClient(client)โ
Set a client identifier for tracking purposes.
Parametersโ
| Parameter | Type | Required | Description |
|---|---|---|---|
client | string | โ | Client identifier (e.g., 'web', 'mobile', 'ios', 'android') |
Exampleโ
Resync.setClient('web');
// or
Resync.setClient('mobile-ios');
Resync.logEvent(event)โ
Log a custom event for analytics and tracking.
Parametersโ
| Parameter | Type | Required | Description |
|---|---|---|---|
event | object | โ | Event object |
event.eventId | string | โ | Event identifier |
event.logId | string | โ | External log ID for correlation |
event.metadata | object | โ | Additional event metadata |
Exampleโ
// Simple event
Resync.logEvent({
eventId: 'evt_user_signup',
});
// Event with metadata
Resync.logEvent({
eventId: 'evt_purchase_completed',
logId: 'order_789',
metadata: {
amount: 99.99,
currency: 'USD',
productId: 'prod_123',
quantity: 2,
},
});
Resync.submitForm(formData)โ
Submit form data to the Resync backend.
Parametersโ
| Parameter | Type | Required | Description |
|---|---|---|---|
formData | object | โ | Form submission object |
formData.contentViewId | number | โ | Content view ID of the form |
formData.data | object | โ | Form field data |
Returnsโ
Promise<boolean | Error> - Returns true if successful, Error otherwise
Exampleโ
try {
const success = await Resync.submitForm({
contentViewId: 456,
data: {
name: 'John Doe',
email: 'john@example.com',
message: 'Hello!',
},
});
if (success) {
console.log('Form submitted successfully');
}
} catch (error) {
console.error('Form submission failed:', error);
}
Resync.subscribe(callback)โ
Subscribe to configuration updates. The callback will be invoked whenever the configuration changes.
Parametersโ
| Parameter | Type | Required | Description |
|---|---|---|---|
callback | (config: AppConfig) => void | โ | Callback function |
Exampleโ
function handleConfigUpdate(config) {
console.log('Config updated:', config);
// Update UI or app state
}
Resync.subscribe(handleConfigUpdate);
Resync.unsubscribe(callback)โ
Unsubscribe from configuration updates.
Parametersโ
| Parameter | Type | Required | Description |
|---|---|---|---|
callback | (config: AppConfig) => void | โ | Previously subscribed callback function |
Exampleโ
Resync.unsubscribe(handleConfigUpdate);
Advanced Usageโ
Real-time Configuration Updatesโ
Subscribe to configuration changes to update your app dynamically:
await Resync.init({
key: 'your-api-key',
appId: 7,
storage: localStorage,
callback: () => {
console.log('Initial config loaded:');
},
environment: 'sandbox'
});
// Subscribe to future updates
Resync.subscribe(() => {
console.log('Config updated!');
// Update your app's state or UI
updateAppSettings();
});
User Segmentation with attributesโ
Combine user attributes for targeted campaigns:
// Set user attributes
await Resync.loginUser('user_123', {
email: 'user@example.com',
name: 'Alice',
});
await Resync.setUserAttributes({
attributes: {
userTier: 'premium',
region: 'north-america',
},
});
// Get variant (assignment may be based on attributes)
const variant = await Resync.getVariant('premium_feature_test');
if (variant) {
// Show experiment variant
} else {
// Show control
}
Dynamic Feature Flagsโ
Use remote config for feature flagging:
// Check if a feature is enabled
const newUIEnabled = Resync.getConfig('ENABLE_NEW_UI');
const darkModeAvailable = Resync.getConfig('DARK_MODE_AVAILABLE');
if (newUIEnabled) {
renderNewUI();
} else {
renderLegacyUI();
}
// Get configuration objects
const apiSettings = Resync.getConfig('API_SETTINGS');
console.log('API timeout:', apiSettings?.timeout);
console.log('Max retries:', apiSettings?.maxRetries);
Event Tracking Pipelineโ
Build a comprehensive event tracking system:
// Track user journey
Resync.logEvent({
eventId: 'evt_app_opened',
metadata: { timestamp: Date.now() },
});
// Track interactions
document.getElementById('cta-button').addEventListener('click', () => {
Resync.logEvent({
eventId: 'evt_cta_clicked',
metadata: {
buttonId: 'cta-button',
page: 'homepage',
},
});
});
// Track conversions
async function completePurchase(orderId, amount) {
await processPayment();
Resync.logEvent({
eventId: 'evt_purchase_completed',
logId: orderId,
metadata: {
amount,
currency: 'USD',
timestamp: Date.now(),
},
});
}
Storage Adaptersโ
Use different storage adapters based on your platform:
Browser (Web)โ
await Resync.init({
key: 'your-api-key',
appId: 7,
storage: localStorage, // or sessionStorage
environment: 'sandbox'
});
React Nativeโ
import AsyncStorage from '@react-native-async-storage/async-storage';
await Resync.init({
key: 'your-api-key',
appId: 7,
storage: AsyncStorage,
environment: 'sandbox'
});
Custom Storage Adapterโ
// Implement your own storage adapter
const customStorage = {
async getItem(key) {
// Your implementation
},
async setItem(key, value) {
// Your implementation
},
async removeItem(key) {
// Your implementation
},
async clear() {
// Your implementation
},
};
await Resync.init({
key: 'your-api-key',
appId: 7,
storage: customStorage,
environment: 'sandbox'
});
TypeScript Supportโ
The library includes comprehensive TypeScript definitions:
import Resync, {
InitOptions,
AppConfig,
ContentView,
Experiment,
ExperimentVariant,
AppEvent,
Storage,
} from 'resync';
// Type-safe initialization
const options: InitOptions = {
key: 'your-api-key',
appId: 7,
callback: () => {
console.log('Resync loaded');
},
storage: localStorage,
};
await Resync.init(options);
// Type-safe event logging
const event: AppEvent = {
eventId: 'evt_user_action',
metadata: {
action: 'click',
target: 'button',
},
};
Resync.logEvent(event);
Platform Supportโ
- โ JavaScript (ES6+) - Modern JavaScript environments
- โ React Native - iOS and Android apps
- โ Expo - Managed and bare workflows
- โ Node.js - Server-side JavaScript (with compatible storage)
- โ Web Browsers - Chrome, Firefox, Safari, Edge
Best Practicesโ
1. Initialize Earlyโ
Initialize Resync as early as possible in your application lifecycle:
// App entry point
import Resync from 'resync';
async function initializeApp() {
await Resync.init({
key: process.env.RESYNC_API_KEY,
appId: parseInt(process.env.RESYNC_APP_ID),
storage: localStorage,
environment: 'sandbox'
});
// Continue app initialization
startApp();
}
initializeApp();
Note: Cache TTL is automatically configured based on your environment:
- Development: No caching (always fetches fresh data for fast iteration)
- Production: 6 hours cache (optimal performance)
2. Handle Errors Gracefullyโ
Always handle potential errors:
try {
await Resync.init({
key: 'your-api-key',
appId: 7,
storage: localStorage,
environment: 'sandbox'
});
} catch (error) {
console.error('Failed to initialize Resync:', error);
// Fallback to default configuration
}
3. Use Environment Variablesโ
Store API credentials securely:
await Resync.init({
key: process.env.RESYNC_API_KEY,
appId: parseInt(process.env.RESYNC_APP_ID),
storage: localStorage,
environment: 'sandbox'
});
4. Automatic Cache Managementโ
The SDK automatically manages caching based on your environment:
await Resync.init({
key: 'your-api-key',
appId: 7,
storage: localStorage,
environment: 'sandbox'
});
// Cache TTL is set automatically:
// - Development: 0ms (no caching, always fresh)
// - Production: 6 hours (21600000ms)
5. Clean Up Subscriptionsโ
Unsubscribe from updates when components unmount:
function MyComponent() {
useEffect(() => {
const handleUpdate = (config) => {
console.log('Config updated:', config);
};
Resync.subscribe(handleUpdate);
return () => {
Resync.unsubscribe(handleUpdate);
};
}, []);
}
Troubleshootingโ
API Key Issuesโ
Problem: "API key is required" error
Solution: Ensure you're passing the API key during initialization:
await Resync.init({
key: 'rsk_live_your_api_key', // Make sure this is set
appId: 7,
storage: localStorage,
environment: 'sandbox'
});
Storage Issuesโ
Problem: "Storage is required" error
Solution: Provide a valid storage object:
// Web
await Resync.init({
key: 'your-api-key',
appId: 7,
storage: localStorage, // Add storage
environment: 'sandbox'
});
// React Native
import AsyncStorage from '@react-native-async-storage/async-storage';
await Resync.init({
key: 'your-api-key',
appId: 7,
storage: AsyncStorage, // Add storage
environment: 'sandbox'
});
Configuration Not Updatingโ
Problem: Configuration values aren't updating in production
Solution: The cache TTL is automatically set based on environment:
- Production: 6 hours cache
- Development: No cache (always fresh)
Licenseโ
MIT
Built with โค๏ธ for developers who ship fast