npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flowly/sdk

v0.0.20

Published

Flowly Attribution SDK — A lightweight, privacy-first solution for tracking marketing attribution, user events, and revenue across web applications. Built with TypeScript support and GDPR compliance in mind.

Readme

Flowly Attribution SDK

npm version license

Flowly Attribution SDK helps you measure user acquisition, conversion events, and revenue with a privacy-first, lightweight approach. Ideal for modern web applications looking for accurate marketing attribution without sacrificing speed or user experience.

🌐 Website | 📚 Documentation


Features

  • 📈 Accurate Attribution — Track page visits, events, conversions, and revenue.
  • 🔒 Privacy-First — GDPR-compliant by design.
  • Lightweight & Fast — Minimal performance impact.
  • 🔧 Highly Configurable — Customize logging, session management, and more.
  • 🚀 Built for Developers — TypeScript support out of the box.

Installation

Install via npm or yarn:

npm install @flowly/sdk
# or
yarn add @flowly/sdk

Or use directly in the browser via CDN:

<script src="https://cdn.jsdelivr.net/npm/@flowly/sdk@latest/dist/flowly-sdk.js"></script>

Replace latest with the specific version number if needed.

When included this way, the SDK is available globally via the Flowly object.

Example:

<script src="https://cdn.jsdelivr.net/npm/@flowly/[email protected]/dist/flowly-sdk.js"></script>
<script>
  const builder = Flowly.builder();
  const flowly = builder
    .apiKey('your-api-key')
    .secret('your-secret-key')
    .appId('your-product-id')
    .productName('your-product-name')
    .build();

  flowly.pageVisit('HomePage');
</script>

Quick Start

import { builder, LogLevel } from '@flowly/sdk';

const flowly = builder()
  .apiKey('your-api-key')
  .secret('your-secret-key')
  .appId('your-product-id')
  .productName('your-product-name')
  .logLevel(LogLevel.Info)
  .sessionTimeout(1800) // Optional: Session timeout in seconds
  .consentSettings({ // Optional: Configure user consent
    isConsentGiven: true,
    analyticsEnabled: true,
    adsPersonalizationEnabled: true
  })
  .build();

// Track page visit
flowly.pageVisit('HomePage');

// Track a custom event using EventBuilder
flowly.newEvent('Signup')
  .withParameter('plan', 'Pro')
  .track();

// Track a conversion event
flowly.conversionEvent('PurchaseCompleted', { orderId: '12345' });

// Track revenue
flowly.revenue('Purchase', 'USD', 99.99, { productId: 'sku_123' });

// Identify and login a user
flowly.login('custom-user-id');

// Logout the current user
flowly.logout();

// Flush pending events
flowly.flush();

API Reference

Builder Methods

| Method | Description | | :--- | :--- | | apiKey(apiKey: string) | Set the API key for authentication. | | secret(secret: string) | Set the API secret for secure authentication. (Note: This is a JS-specific method for the builder. The common Kotlin FlowlyBuilder interface does not define secret.) | | appId(appId: string) | Set your product ID. | | productName(productName: string) | Set your product name. | | customUserId(customUserId: string) | Set a custom user identifier. | | logLevel(logLevel: LogLevel) | Define the logging level (Verbose, Debug, Info, etc.). | | sessionTimeout(sessionTimeout: number) | Set session timeout (seconds). | | flowlyDeviceId(deviceId: string) | Optionally set a custom device ID. | | autoPersistDomain(autoPersistDomain: string) | Auto-persist across subdomains. | | baseUrl(baseUrl: string) | Override the default API base URL. | | consentSettings(settings: ConsentSettings): FlowlyBuilder | Configure initial user consent settings. | | attributionWindowConfig(config: AttributionWindowConfig): FlowlyBuilder | Configure attribution window settings (e.g., click-through and view-through windows). | | build() | Initialize and build the FlowlyController instance. |

FlowlyController Methods

| Method | Description | | :--- | :--- | | pageVisit(pageName: string) | Track a page visit. | | event(eventName: string, args: any) | Track a generic custom event. | | conversionEvent(eventName: string, args: any) | Track a conversion-specific event. | | revenue(eventName: string, currency: string, amount: number, args: any) | Track revenue-related events. | | login(customUserId: string) | Identify and login a user. | | logout() | Logout the current user. | | flush() | Force send all pending events immediately. | | getDeviceId() | Retrieve the device identifier used by the SDK. | | newEvent(eventName: string): EventBuilder | Start building a custom event. Returns an EventBuilder. | | newConversionEvent(eventName: string): EventBuilder | Start building a conversion event. Returns an EventBuilder. | | newRevenueEvent(eventName: string, currency: string, amount: number): EventBuilder | Start building a revenue event. Returns an EventBuilder. | | getState(): ControllerState | Get the current state of the SDK controller (e.g., STARTED, PAUSED). | | pause(): void | Pause event tracking. Events will be queued or discarded based on SDK policy when paused. | | resume(): void | Resume event tracking if previously paused. | | getConsentSettings(): ConsentSettings | Get the current consent settings applied to the SDK. | | updateConsentSettings(settings: ConsentSettings): void | Update user consent settings at runtime. Changes take effect immediately. | | getSessionId(): string | Get the identifier for the current user session. | | getGlobalProperties(): any | Get the currently set global properties that are automatically included with events. | | setGlobalProperties(properties: any): void | Set global properties to be included with all subsequent events. | | handleDeepLink(url: string, callback?: (deepLinkData: DeepLinkData | null) => void): void | Process a deep link URL. The optional callback receives the processed DeepLinkData or null. | | adRevenue(adPlatform: string, adSource: string, adUnitId: string, adFormat: string, value: number, currency: string, args?: object): void | Track revenue generated from advertisements. | | getAttributionInfo(callback: (attributionData: AttributionData | null) => void): void | Retrieves attribution information. The callback receives an AttributionData object or null. | | getAttributionData(): AttributionData | null | Synchronously retrieve the resolved attribution information. May return null if data is not yet available. | | updatePostbackConversionValue(conversionValue: number, coarseValue?: string, lockWindow?: boolean): void | (iOS SKAdNetwork) Update the conversion value. coarseValue and lockWindow are for SKAN 4.0. | | setPushToken(token: string, type: string): void | Set the push notification token. type can be 'fcm', 'apns', 'hms', etc. (Common string values for type include "fcm" for Firebase Cloud Messaging, "apns" for Apple Push Notification service). | | enableUninstallTracking(enabled: boolean): void | Enable or disable uninstall tracking (if supported by the platform and configuration). | | setInstallReferrer(referrer: string): void | Set the install referrer string (e.g., from Play Store on Android or other sources). Should be called early. | | getLatestDeepLinkData(): DeepLinkData | null | Synchronously retrieve the most recently processed deep link data. | | setEventSentCallback(callback: ((eventName: string, eventType: string, eventArgs: object | null) => void) | null): void | Set a callback to be invoked after an event is processed by the SDK. | | setSessionStartCallback(callback: ((sessionId: string) => void) | null): void | Set a callback to be invoked when a new session starts. | | verifyPurchase(purchaseInfo: PurchaseData, callback: (result: VerificationResult) => void): void | Send purchase information for verification or tracking. | | trackSubscriptionStart(productId: string, details?: object): void | Track the start of a subscription. | | trackSubscriptionRenewal(productId: string, details?: object): void | Track a subscription renewal. | | trackSubscriptionCancel(productId: string, details?: object): void | Track a subscription cancellation. | | trackTrialStart(productId: string, details?: object): void | Track the start of a trial period. |


E-commerce Events

Track specific e-commerce actions. These methods typically accept structured parameter objects.

| Method | Description | | :------------------------------------------------ | :----------------------------------------------------- | | trackPurchase(params: ECommercePurchaseParams) | Track a completed purchase with detailed parameters. | | trackViewItem(params: ECommerceViewItemParams) | Track a view of a specific item or product. | | trackAddToCart(params: ECommerceAddToCartParams)| Track an item being added to the cart. |

(Note: ECommercePurchaseParams, ECommerceViewItemParams, and ECommerceAddToCartParams are typically plain JavaScript objects corresponding to complex structures defined in the core Kotlin SDK. Refer to Kotlin documentation for detailed structure if needed.)

Example for E-commerce:

// Assuming ECommercePurchaseParams is an object like:
// { transactionId: 'txn123', currency: 'USD', value: 59.99, items: [{itemId: 'p1', quantity: 1, price: 59.99}], ... }
flowlyInstance.trackPurchase({
  transactionId: 'T12345',
  value: 75.50,
  currency: 'USD',
  items: [
    { itemId: 'SKU001', itemName: 'Cool T-Shirt', quantity: 1, price: 25.00, category: 'Apparel' },
    { itemId: 'SKU002', itemName: 'Awesome Mug', quantity: 2, price: 12.75, category: 'Accessories' }
  ],
  shipping: 5.00,
  tax: 5.50
});

flowlyInstance.trackViewItem({
  items: [{ itemId: 'SKU003', itemName: 'Another Product', category: 'Gadgets', price: 100.00 }],
  currency: 'USD', // Optional if item prices include currency or a global one is assumed
  // other relevant parameters like item_list_name
});

flowlyInstance.trackAddToCart({
  items: [{ itemId: 'SKU004', itemName: 'Fancy Hat', quantity: 1, price: 30.00, category: 'Apparel' }],
  value: 30.00, // Total value of items added
  currency: 'USD'
});

Utilities

| Function | Description | | :--- | :--- | | isEnabled(): boolean | Returns true if tracking is currently enabled. | | setEnabled(enabled: boolean) | Enable or disable event tracking at runtime. | | isInitialized(): boolean | Check if the SDK has been initialized. | | getInstance(): FlowlyController \| null | Get the existing FlowlyController instance. |

LogLevel Enum

Control the verbosity of SDK logs:

LogLevel.Verbose  // Detailed logs
LogLevel.Debug    // Debugging information
LogLevel.Info     // General information
LogLevel.Warn     // Warnings
LogLevel.Error    // Errors
LogLevel.Assert   // Assertions

EventBuilder Interface

The EventBuilder provides a fluent interface to construct and send events with multiple custom parameters. You obtain an EventBuilder instance by calling newEvent(), newConversionEvent(), or newRevenueEvent() on the FlowlyController.

| Method | Description | | :----------------------------------- | :------------------------------------------------ | | withParameter(key: string, value: any): EventBuilder | Add a custom key-value parameter to the event. | | track(): void | Finalize and send the event. |

Example:

flowly.newEvent('PlayerUpdate')
  .withParameter('level', 5)
  .withParameter('score', 1500)
  .track();

ControllerState Enum

Represents the operational state of the Flowly SDK. Accessed via flowly.getState().

| State | Description | | :------------ | :---------------------------------------------------------- | | NOT_STARTED | The SDK has not been initialized or has been shut down. | | STARTED | The SDK is initialized and actively tracking events. | | PAUSED | The SDK is initialized but event tracking is temporarily paused. |

ConsentSettings Object

The ConsentSettings object allows you to specify user consent preferences. It's used with builder.consentSettings() during initialization and flowly.updateConsentSettings() at runtime.

Properties:

| Property | Type | Description | | :------------------------ | :------ | :-------------------------------------------------------------------------- | | isConsentGiven | boolean | General consent for tracking. If false, other flags are typically ignored. | | analyticsEnabled | boolean | Consent for tracking general analytics and usage patterns. | | adsPersonalizationEnabled | boolean | Consent for collecting data for personalized advertising. | | dataSharingEnabled | boolean | Consent for sharing data with third-party partners. |

Example:

// To be used with builder.consentSettings() or flowly.updateConsentSettings()
const userConsent = {
  isConsentGiven: true,
  analyticsEnabled: true,
  adsPersonalizationEnabled: false // User opted out of ad personalization
};

// Example: Set initial consent during SDK build
// const flowly = builder()
//   .apiKey('your-api-key')
//   // ... other builder methods
//   .consentSettings(userConsent)
//   .build();

// Example: Update consent at runtime
// flowly.updateConsentSettings(userConsent);

(Note: The ConsentSettings object in Kotlin has static helper methods noConsent() and fullConsent(). Their availability in JS depends on JsExport of companion objects. If not directly available, create the object manually as shown above.)

AttributionData Object

Describes the resolved attribution information for the user. Accessed via flowly.getAttributionInfo().

| Property | Type | Description | | :------------- | :------------ | :-------------------------------------------------------------------------- | | network? | string | The ad network or source that the attribution is credited to. | | campaign? | string | The specific campaign name. | | adgroup? | string | The ad group name. | | creative? | string | The ad creative name or identifier. | | clickLabel? | string | Unique identifier for the touchpoint (e.g., click ID). | | attributedAt?| number | Timestamp (milliseconds since epoch) when the attribution was resolved. | | rawData? | object | A map containing any other raw parameters associated with the attribution. |

Example:

// Structure of AttributionData object received in getAttributionInfo callback
// const attribution = {
//   network: "some_network",
//   campaign: "campaign_name",
//   attributedAt: 1678886400000, // Example timestamp
//   rawData: { custom_param: "value" }
// };

PurchaseData Object

Used with flowly.verifyPurchase() to send purchase details.

| Property | Type | Description | | :-------------- | :---------- | :------------------------------------------------------------------------- | | productId | string | Identifier for the product purchased. | | transactionId | string | Unique identifier for the transaction. | | receiptData | string | Receipt data (e.g., base64 encoded string, or JSON string from store). | | currency | string | ISO 4217 currency code for the transaction amount (e.g., "USD"). | | amount | number | The monetary value of the transaction. | | extras? | object | Optional map for any additional custom key-value data related to the purchase. |

VerificationResult Object

Received in the callback from flowly.verifyPurchase().

| Property | Type | Description | | :-------------- | :------ | :-------------------------------------------------------------------------- | | success | boolean | Indicates if the SDK successfully processed/sent the verification request. | | message? | string | Optional message providing more details about the outcome. | | transactionId?| string | Echoes back the transaction ID from the PurchaseData. |


Example

import { builder, LogLevel, isInitialized, getInstance } from '@flowly/sdk';

if (!isInitialized()) {
  builder()
    .apiKey('your-api-key')
    .secret('your-secret-key')
    .appId('your-product-id')
    .productName('your-product-name')
    .logLevel(LogLevel.Warn)
    .sessionTimeout(1800)
    .consentSettings({ // Example: Configure user consent
      isConsentGiven: true,
      analyticsEnabled: true,
      adsPersonalizationEnabled: false // User opts out of ad personalization
    })
    .build();
}

const flowlyInstance = getInstance();
flowlyInstance?.pageVisit('LandingPage');

// Example of using EventBuilder
flowlyInstance?.newEvent('NewsletterSignup')
  .withParameter('newsletter', 'TechWeekly')
  .track();

// Example of setting an event callback
flowlyInstance?.setEventSentCallback((eventName, eventType, eventArgs) => {
  console.log(`Event Sent: ${eventType} - ${eventName}`, eventArgs || {});
});

// Example of getting attribution info (asynchronous)
flowlyInstance?.getAttributionInfo(function(attributionData) {
  if (attributionData) {
    console.log('Async Attribution - Network:', attributionData.network, 'Campaign:', attributionData.campaign);
  } else {
    console.log('Async Attribution: No data yet.');
  }
});

// Example of getting attribution data (synchronous)
const currentAttribution = flowlyInstance?.getAttributionData();
if (currentAttribution) {
  console.log('Sync Attribution - Network:', currentAttribution.network, 'Campaign:', currentAttribution.campaign);
} else {
  console.log('Sync Attribution: No data available or SDK not initialized.');
}

// Example of setting a push token
flowlyInstance?.setPushToken('your-push-token-here', 'fcm');
console.log('Push token set.');

// Example of tracking an E-commerce purchase event
flowlyInstance?.trackPurchase({
  transactionId: 'TXN789123',
  value: 120.50,
  currency: 'EUR',
  items: [
    { itemId: 'PROD456', itemName: 'Advanced Widget', quantity: 1, price: 100.00, category: 'Electronics' },
    { itemId: 'SERV01', itemName: 'Support Plan', quantity: 1, price: 20.50, category: 'Services' }
  ],
  shipping: 10.00,
  tax: 10.50
});
console.log('E-commerce purchase tracked.');

Best Practices

  • 🚀 Initialize Early — Initialize Flowly SDK as soon as your app loads to capture all events.
  • 📖 Use Meaningful Event Names — Helps with better analytics and attribution reports.
  • 🔒 Respect Privacy — Never log sensitive personal information.
  • 📦 Flush Before Exit — Flush events before page unload or user logout to ensure data is sent.

License

This project is licensed under the MIT License.


Support

If you encounter any issues or have questions, please reach out: