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

@qredex/agent

v1.1.4

Published

Lightweight browser agent for Qredex intent capture and locking

Readme

span

@qredex/agent

Deterministic browser runtime for Qredex intent capture, locking, and PIT handoff.

CI Release npm version bundle size license


Quick Start

1. Choose an Install Path

CDN / script tag

<!-- Add before </body> -->
<script src="https://cdn.qredex.com/agent/v1/qredex-agent.iife.min.js"></script>

For local engineer E2E, dev CDN usage, and local Core sandbox setup, see docs/DEVELOPMENT.md.

Core package

npm install @qredex/agent

Framework wrappers

npm install @qredex/react
npm install @qredex/vue
npm install @qredex/svelte
npm install @qredex/angular

The wrapper packages include @qredex/agent, so framework consumers only need the wrapper package.

2. Attribution Sequence

Qredex attribution sequence

The agent never adds to cart, removes items, or clears the merchant cart. The storefront owns cart state, checkout, and order submission; the agent only captures intent, locks IIT to PIT, and exposes PIT for backend attribution.

3. Connect Cart And Checkout

Your storefront owns cart mutations and order creation. Qredex only needs the merchant-reported cart transition so it can lock IIT to PIT. After lock, the merchant reads that PIT and carries it with the normal order payload to the merchant backend or direct Qredex order ingestion path, where attribution is resolved.

const agent = window.QredexAgent;

async function addToCart(product) {
  // [Merchant] Snapshot the current cart before your platform changes it.
  const previousCount = cart.itemCount;

  // [Merchant] Perform the real cart mutation in your own backend/storefront.
  await api.post('/cart', product);

  // [Qredex] Report the cart transition after the merchant cart is updated.
  agent.handleCartChange({
    itemCount: cart.itemCount,
    previousCount,
  });
}

async function removeFromCart(line) {
  // [Merchant] Snapshot the current cart before your platform changes it.
  const previousCount = cart.itemCount;

  // [Merchant] Perform the real cart mutation in your own backend/storefront.
  await api.delete(`/cart/${line.id}`);

  // [Qredex] Report the new live cart state so attribution can stay in sync.
  agent.handleCartChange({
    itemCount: cart.itemCount,
    previousCount,
  });
}

async function clearCart() {
  // [Merchant] Clear the real cart in your own system first.
  await api.post('/cart/clear');

  // [Qredex] Clear IIT/PIT because the merchant cart is now empty.
  agent.handleCartEmpty();
}

async function checkout(order) {
  // [Qredex] Read the locked PIT that must travel with this order.
  const pit = agent.getPurchaseIntentToken();

  // [Merchant] Submit your normal order payload and include the PIT so the
  // backend can forward order + PIT into Qredex attribution ingestion.
  await api.post('/orders', {
    ...order,
    qredex_pit: pit,
  });

  // [Merchant + Qredex] Reuse the same clear path after checkout succeeds.
  await clearCart();
}

4. Done!

The agent automatically:

  • ✅ Captures qdx_intent from URL
  • ✅ Stores IIT in browser storage (sessionStorage + cookie fallback)
  • ✅ Locks IIT → PIT when the merchant reports a non-empty cart and the state is lockable
  • ✅ Clears PIT when the merchant reports that the cart became empty or checkout succeeds
  • ✅ Exposes PIT so the merchant/backend can carry it into order attribution

What Merchants Actually Call

| Merchant event | Call | Why | | -------------------------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------- | | User lands from Qredex link | No manual call required | The agent capturesqdx_intent automatically | | Cart becomes non-empty | handleCartChange({ itemCount, previousCount }) | Gives Qredex the live cart state so IIT can lock to PIT | | Cart changes while still non-empty | handleCartChange(...) | Safe retry path on the next merchant-reported non-empty cart event if a previous lock failed | | Clear cart action | clearCart() -> handleCartEmpty() | Clears IIT/PIT from the live session | | Need PIT for order submission | getPurchaseIntentToken() | Attach PIT to the order or checkout payload | | Checkout completes without a cart-empty step | handlePaymentSuccess() | Optional explicit cleanup path |


What is Qredex Agent?

Qredex Agent is a lightweight browser runtime (~5KB minified) that:

  1. Captures the qdx_intent token from URLs when users arrive via Qredex tracking links
  2. Stores the token securely in browser storage (sessionStorage + cookie fallback)
  3. Locks the token via Qredex API when the merchant reports a non-empty cart
  4. Owns attribution state throughout the shopping session
  5. Exposes the Purchase Intent Token (PIT) so the merchant/backend can carry it into order ingestion

Qredex is not a cart SDK or checkout SDK. The merchant owns commerce actions. Qredex owns deterministic attribution state: capture IIT, lock IIT to PIT when the merchant reports a real cart, then make PIT available for the order path.

Key Features

  • Zero dependencies - Pure vanilla JavaScript, works everywhere
  • Idempotent operations - Safe to call multiple times
  • Retry on failure - Automatically retries lock if it fails
  • Storage fallback - Uses sessionStorage first, cookies as fallback

API Reference

Read Tokens

// Get Influence Intent Token (IIT) - captured from URL
QredexAgent.getInfluenceIntentToken()     // string | null

// Get Purchase Intent Token (PIT) - locked via API
QredexAgent.getPurchaseIntentToken()      // string | null

// Check if IIT exists
QredexAgent.hasInfluenceIntentToken()     // boolean

// Check if PIT exists
QredexAgent.hasPurchaseIntentToken()      // boolean

State Inspection

// Canonical snapshot for browser integrations, support, and workbenches
const state = QredexAgent.getState();
// Returns:
// {
//   initialized: boolean,
//   lifecycleState: 'idle' | 'running' | 'locking' | 'destroyed',
//   lockInProgress: boolean,
//   lockAttempts: number,
//   hasIIT: boolean,
//   hasPIT: boolean,
//   iit: string | null,
//   pit: string | null,
//   cartState: 'unknown' | 'empty' | 'non-empty',
//   locked: boolean,
//   timestamp: number
// }

Tiny Support Panel

<button onclick="renderQredexDebug()">Refresh Qredex state</button>
<pre id="qredex-debug"></pre>

<script>
  function renderQredexDebug() {
    const snapshot = QredexAgent.getState();
    document.getElementById('qredex-debug').textContent =
      JSON.stringify(snapshot, null, 2);
  }

  renderQredexDebug();
</script>

Event Handlers (Merchant → Agent)

Tell the agent when events happen:

// Canonical path: report every cart count transition
QredexAgent.handleCartChange({
  itemCount: 1,
  previousCount: 0,
});

// Add one more item later
QredexAgent.handleCartChange({
  itemCount: 2,
  previousCount: 1,
});

// Remove one item but keep cart non-empty
QredexAgent.handleCartChange({
  itemCount: 1,
  previousCount: 2,
});

// Clear cart completely
QredexAgent.handleCartEmpty();

// Optional explicit cleanup if your platform does not emit a cart-empty step
QredexAgent.handlePaymentSuccess();

Behavior:

| Event | Example | Agent behavior | | -------------------------------------------- | -------------------- | ------------------------------------------------------------------------- | | Empty cart becomes non-empty | empty cart -> 1 item | Attempts IIT -> PIT lock | | Merchant reports a live non-empty cart again | 1 item -> 2 items | Attempts or retries IIT -> PIT lock if IIT exists and PIT is still absent | | Partial remove | 2 items -> 1 item | No clear; attribution stays attached to the live cart |

Minimum Correct Merchant Sequence

// 1. Load the script (CDN auto-inits by default)
// 2. Merchant reports a real cart transition
QredexAgent.handleCartChange({ itemCount: 1, previousCount: 0 });

// 3. Merchant reads PIT during checkout/order assembly
const pit = QredexAgent.getPurchaseIntentToken();

// 4. Merchant sends order + PIT to their backend
await fetch('/orders', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ ...order, qredex_pit: pit }),
});

// 5. Merchant clears attribution after checkout if needed
QredexAgent.handlePaymentSuccess();

Merchant Integration Checklist

  • Load the agent and let it auto-init
  • Report every real merchant cart transition with handleCartChange(...)
  • Read PIT with getPurchaseIntentToken() during checkout or order assembly
  • Send order + PIT to your backend or direct ingestion path
  • Clear attribution with handleCartEmpty() or handlePaymentSuccess()

Tiny Cart Restore Helper

function syncRestoredCart(restoredItemCount) {
  if (restoredItemCount > 0) {
    // On refresh, treat merchant cart restore as empty -> non-empty unless you
    // already track a previous merchant cart count elsewhere.
    QredexAgent.handleCartChange({
      itemCount: restoredItemCount,
      previousCount: 0,
    });
  }
}

Event Listeners (Agent → Merchant)

Optional observability hooks.

Most merchants only need:

  • onStateChanged to reflect attribution state in UI or debug panels
  • onError to surface integration mistakes and lock failures

Use these only if you want extra lifecycle visibility:

  • onLocked
  • onCleared
  • onIntentCaptured

Listen for agent events:

// Listen for successful lock
QredexAgent.onLocked(({ purchaseToken, alreadyLocked, timestamp }) => {
  console.log('🔒 Locked:', purchaseToken);
  console.log('Already locked:', alreadyLocked);
});

// Listen for cleared state
QredexAgent.onCleared(({ reason, timestamp }) => {
  console.log('🗑️ Cleared because', reason);
});

// Listen for errors
QredexAgent.onError(({ code, message, context }) => {
  console.error('❌ Error in', context, code, message);
});

// Listen for attribution state changes (NEW)
QredexAgent.onStateChanged(({ hasIIT, hasPIT, locked, cartState }) => {
  console.log('State changed:', { hasIIT, hasPIT, locked, cartState });
});

// Listen for IIT capture (NEW)
QredexAgent.onIntentCaptured(({ timestamp }) => {
  console.log('✅ Intent captured at:', new Date(timestamp));
});

Unregister Listeners

const lockedHandler = ({ purchaseToken }) => {
  console.log('Locked:', purchaseToken);
};

QredexAgent.onLocked(lockedHandler);
// ... later
QredexAgent.offLocked(lockedHandler);

const errorHandler = ({ code, message }) => {
  console.error(code, message);
};

QredexAgent.onError(errorHandler);
// ... later
QredexAgent.offError(errorHandler);

Manual Commands

// Manual lock (idempotent - safe to call multiple times)
const result = await QredexAgent.lockIntent();

// Result type:
// { success: true, purchaseToken: 'pit_xxx', alreadyLocked: false }
// { success: false, purchaseToken: null, alreadyLocked: false, error: '...' }

// Clear intent state (after checkout or cart empty)
QredexAgent.clearIntent();

Pass meta only if you intentionally want to attach extra merchant context to the lock request.

Lifecycle Methods

// Initialize with custom config
// CDN/IIFE auto-starts on script load; ESM/framework usage should call init() in the browser.
QredexAgent.init({
  debug: true,
  useMockEndpoint: true,
});

// Check if initialized
QredexAgent.isInitialized();  // boolean

// Destroy agent and clean up listeners (for SPA route changes)
QredexAgent.destroy();

// Alias for destroy()
QredexAgent.stop();

Installation

CDN (Recommended)

<script src="https://cdn.qredex.com/agent/v1/qredex-agent.iife.min.js"></script>

Versioned URLs:

<!-- Auto-updates to latest v1.x.x -->
<script src="https://cdn.qredex.com/agent/v1/qredex-agent.iife.min.js"></script>

<!-- Pinned version (immutable) -->
<script src="https://cdn.qredex.com/agent/v1.0.0/qredex-agent.iife.min.js"></script>

NPM

npm install @qredex/agent
// ESM import
import {
  handleCartChange,
  getPurchaseIntentToken,
  onLocked,
} from '@qredex/agent';

// Or default import
import QredexAgent from '@qredex/agent';

QredexAgent.init();

For React, Vue, Svelte, or Angular, use the matching wrapper from the Quick Start section above and follow that package README for framework-specific usage.


Configuration

Optional configuration via window.QredexAgentConfig. Set before the script loads:

<script>
  window.QredexAgentConfig = {
    debug: true,
    autoInit: true,
    useMockEndpoint: true,
  };
</script>
<script src="http://localhost:3000/dist/qredex-agent.iife.dev.min.js"></script>

Configuration Options

| Option | Type | Default | Description | | ----------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | autoInit | boolean | true | CDN/IIFE preload only. Default and recommended. Setfalse only for advanced script-tag integrations that need to call init() themselves | | debug | boolean | false | Non-production logging. Forced tofalse in production | | useMockEndpoint | boolean | false | ⚠️DEVELOPMENT ONLY for merchant usage. Generates fake PIT tokens locally |

Production does not support runtime endpoint overrides, storage-key overrides, or mock mode. The production bundle always uses the built-in Qredex production lock endpoint and stable storage keys.

The canonical browser path is:

  • script loads
  • agent auto-inits
  • agent auto-captures IIT from qdx_intent if present

Merchants should not manually capture IIT. That is always agent-owned.

If you disable CDN auto-init, call QredexAgent.init() yourself after the script loads. This is an advanced escape hatch, not the recommended path:

<script>
  window.QredexAgentConfig = { autoInit: false, debug: true };
</script>
<script src="https://cdn.qredex.com/agent/v1/qredex-agent.iife.min.js"></script>
<script>
  QredexAgent.init();
</script>

For real non-production network testing, build the bundle with QREDEX_AGENT_LOCK_ENDPOINT so the endpoint is baked into the staging/dev artifact instead of passed at runtime.


Examples

Quick Test

The fastest way to test Qredex Agent:

# Build the development IIFE bundle, start the local server, and open the test page
npm run example

If the browser does not open automatically:

open http://localhost:3000/examples/index.html

Then:

  • Start with the featured CDN card
  • Simulate intent URL by adding ?qdx_intent=test123 to the CDN page URL and pressing Enter
  • Add to cart and watch PIT get locked
  • Empty cart and watch PIT get cleared

See: examples/README.md for complete example and testing scenarios.

Vanilla JS

const agent = window.QredexAgent;

async function reportCart(previousCount, itemCount) {
  // [Qredex] This is the one call that keeps attribution aligned with your cart.
  agent.handleCartChange({
    previousCount,
    itemCount,
  });
}

document.querySelector('.add-to-cart').addEventListener('click', async (event) => {
  const button = event.currentTarget;
  const product = {
    id: button.dataset.productId,
    price: parseFloat(button.dataset.price),
  };
  // [Merchant] Capture the cart count before your mutation runs.
  const previousCount = cart.itemCount;

  // [Merchant] Add the item using your existing cart endpoint.
  await fetch('/api/cart', {
    method: 'POST',
    body: JSON.stringify(product),
  });

  // [Qredex] Tell Qredex what the cart count changed from and to.
  reportCart(previousCount, cart.itemCount);
});

document.querySelector('.remove-from-cart').addEventListener('click', async (event) => {
  const button = event.currentTarget;
  const line = {
    id: button.dataset.lineId,
    productId: button.dataset.productId,
    price: parseFloat(button.dataset.price),
  };
  // [Merchant] Capture the cart count before your mutation runs.
  const previousCount = cart.itemCount;

  // [Merchant] Remove the item using your existing cart endpoint.
  await fetch(`/api/cart/${line.id}`, {
    method: 'DELETE',
  });

  // [Qredex] Report the resulting cart state back to the agent.
  reportCart(previousCount, cart.itemCount);
});

document.querySelector('.clear-cart').addEventListener('click', async () => {
  const previousCount = cart.itemCount;

  // [Merchant] Clear the real cart in your own system first.
  await fetch('/api/cart/clear', {
    method: 'POST',
  });

  // [Qredex] Report the empty-cart transition so attribution is cleared.
  reportCart(previousCount, 0);
});

Error Handling

Common Issues

Token Not Found

Symptoms: getInfluenceIntentToken() returns null

Solutions:

  1. Check URL parameter is exactly ?qdx_intent=xxx
  2. Reload the page
  3. Verify sessionStorage is available (not private browsing)
  4. Check cookie fallback is working

Lock Fails Silently

Symptoms: Add to cart clicked but PIT not created

Solutions:

  1. Check IIT exists: QredexAgent.hasInfluenceIntentToken()
  2. Check Network tab for API errors
  3. Verify CORS is configured on backend
  4. Check error listener: QredexAgent.onError(handler)

Event Listeners Not Firing

Symptoms: Handlers registered but not called

Solutions:

  1. Verify handler is registered before event occurs
  2. Check handler function signature matches expected params
  3. Ensure handler not unregistered accidentally

Debug Mode

Enable debug logging in development, staging, or test:

window.QredexAgentConfig = { debug: true };

Production always forces debug back to false and suppresses agent debug/info/warn console output.

Example output:

[QredexAgent] Intent token captured from URL
[QredexAgent] Cart change event received { itemCount: 1, previousCount: 0 }
[QredexAgent] Cart has items, IIT exists, no PIT - attempting lock
[QredexAgent] Sending lock request to: https://api.qredex.com/...
[QredexAgent] Intent locked successfully
[QredexAgent] Purchase token stored

Check Storage

Open DevTools → Application → Storage:

Session Storage:

  • __qdx_iit - IIT token
  • __qdx_pit - PIT token

Cookies:

  • __qdx_iit - IIT fallback
  • __qdx_pit - PIT fallback

Browser Support

| Browser | Version | | ------- | ------- | | Chrome | Latest | | Firefox | Latest | | Safari | Latest | | Edge | Latest |

Requirements: ES2020+, sessionStorage, cookies enabled


Documentation

| Document | Description | | -------------------------------------------------------- | ------------------------------------------------------- | | Development | Engineer-only dev CDN, local Core, and sandbox guidance | | Integration Model | Complete integration guide with 2 paths | | API Reference | Full API documentation | | Cart Change Behavior | handleCartChange() state transitions | | Cart Empty Policy | Attribution clearing rationale | | Examples Guide | Examples, local run flow, and testing scenarios | | AGENTS.md | Development guidelines |


Examples Directory

| Example | Description | Quick Start | | ---------------------------------------------------------------------------- | --------------------------------------- | ----------------- | | examples/index.html | Example hub for CDN and wrapper pages | npm run example | | examples/cdn/index.html | Canonical script-tag customer path | Open from the hub | | examples/wrappers/react/index.html | Real React app using@qredex/react | Open from the hub | | examples/wrappers/vue/index.html | Real Vue app using@qredex/vue | Open from the hub | | examples/wrappers/svelte/index.html | Real Svelte app using@qredex/svelte | Open from the hub | | examples/wrappers/angular/index.html | Real Angular app using@qredex/angular | Open from the hub |

Each example includes:

  • A focused integration path
  • The same IIT/PIT cart scenario for behavior checks
  • Real framework apps for React, Vue, Svelte, and Angular
  • Debugging guide

See: examples/README.md for detailed example and testing instructions.


License

Apache-2.0


Support

For questions: [email protected]