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

audiencemanager-js

v0.2.5

Published

Klientbibliotek för audiencemanager Lead Ingest API – retry, auto-idempotens och typad felhantering.

Readme

audiencemanager-js

Klientbibliotek för audiencemanager Lead Ingest API. Wrappar POST /api/public/source/v1/leads med inbyggd retry, auto-idempotens, lokal validering och typad felhantering.

För dig som äger en egen tjänst: du behöver inte ändra AudienceManager-kod. Skapa en API-nyckel under Sources, skicka payloads från din backend, och håll nyckeln borta från webbläsaren.

Installation

npm install audiencemanager-js

I Deno (t.ex. edge functions) behövs ingen installation:

import { AudienceManagerClient } from "npm:audiencemanager-js";

Paketet byggs som fristående ESM (zod är inbakad). Exports:

| Import | Syfte | | --- | --- | | audiencemanager-js | Klient + submit + schema | | audiencemanager-js/contract | Delad v1/v2-schema (server/SDK) | | audiencemanager-js/forms | Formulärfält-validators utan API-nyckel |

Snabbstart (v2 – rekommenderat)

import { AudienceManagerClient } from "audiencemanager-js";

const client = new AudienceManagerClient({
  apiKey: process.env.AM_API_KEY!, // skapas under Sources i appen — endast på servern
});

const result = await client.submitLead({
  schema_version: "v2",
  lead_type: "service", // routing-sträng som avtalats i AM
  external_id: "order-10231",
  contact: {
    first_name: "Anna",
    last_name: "Lind",
    email: "[email protected]",
    phone: "+46701234567",
  },
  location: {
    postal_code: "12345",
    city: "Stockholm",
    address: "Exempelgatan 1",
  },
  request_data: {
    service: {
      category: "cleaning",
      type: "home_cleaning",
      description: "Veckostädning",
    },
    property: { type: "apartment", area_sqm: 68 },
  },
  extensions: {
    // Nischfält som inte finns i standardkontraktet ännu
    preferred_cleaner_id: "c-9",
  },
  attribution: { utm_source: "google" },
});

if (result.status === "accepted") console.log("Lead:", result.lead_id);
if (result.status === "duplicate") console.log("Redan inskickat:", result.lead_id);
if (result.status === "rejected") console.error("Avvisat:", result.errors);

Minimal payload (alla business-fält är valfria):

await client.submitLead({
  schema_version: "v2",
  lead_type: "service",
  contact: { email: "[email protected]" },
  request_data: { service: { description: "Hej" } },
});

Vehicle-exempel:

await client.submitLead({
  schema_version: "v2",
  lead_type: "vehicle",
  contact: { first_name: "Bo", last_name: "Berg", phone: "+46701112233" },
  location: { city: "Göteborg", postal_code: "41101", country_code: "SE" },
  request_data: {
    vehicle: { make: "Volvo", model: "V60", model_year: 2019, mileage: 4500 },
    valuation: { dealer: { min: 120000, max: 140000 } },
  },
});

Utan schema_version (eller med "v1") gäller legacy-kontraktet: öppen request_data, geografi på contact.

Var lägger jag fält?

| Sektion | Innehåll | Auto-mappas? | | --- | --- | --- | | contact | Person: namn, e-post, telefon | Ja (v2 standard) | | location | Plats för uppdrag/fastighet (inte automatiskt bostad) | Ja (v2 standard) | | request_data | Typade sektioner: service, property, vehicle, valuation | Ja för kända sökvägar | | attribution | UTM + landing_page | Ja | | extensions | Custom / framtida vertikal | Nej — lagras; mappa manuellt i AM om det behövs för regler/kort |

Okända nycklar i contact / location / request_data / attribution avvisas på v2. Lägg dem i extensions.

Typed verticals i den här releasen: cleaning-formad service + vehicle. Mäklare, rug cleaning, övriga nischer → extensions tills de får egna sektioner.

Blank/null = saknas. false och 0 behålls. Ogiltiga värden (t.ex. trasig e-post) ger valideringsfel även om fältet är valfritt.

Browser vs server

  • Server: AudienceManagerClient + API-nyckel
  • Browser: importera audiencemanager-js/forms för fältvalidering — skicka aldrig API-nyckeln till klienten

Beteende

  • Auto-idempotens: varje anrop får en Idempotency-Key automatiskt – ext:<external_id> om den finns, annars en UUID. Omförsök återanvänder samma nyckel. Tidigare avvisade eller failed anrop blockerar inte en korrigerad omsändning.
  • Retry med backoff: nätverksfel, 429 och 5xx upp till 3 gånger.
  • Lokal validering: samma zod-regler som servern (validate: false stänger av).

Felhantering

import {
  AudienceManagerError,
  AuthError,
  ValidationError,
  PayloadTooLargeError,
  NetworkError,
} from "audiencemanager-js";

try {
  await client.submitLead(payload);
} catch (err) {
  if (err instanceof AuthError) {
    // 401 – kontrollera API-nyckeln
  } else if (err instanceof ValidationError) {
    // lokal validering – err.issues listar felfälten
  } else if (err instanceof PayloadTooLargeError) {
    // 413 – max 200 KB
  } else if (err instanceof NetworkError) {
    // nätverksfel/5xx kvarstod efter alla omförsök
  } else if (err instanceof AudienceManagerError) {
    // övriga API-fel – err.code, err.status
  }
}

En payload som passerar lokal validering men avvisas av servern returneras som { status: "rejected", errors: [...] }.

API

new AudienceManagerClient(options)

| Option | Typ | Default | Beskrivning | | --- | --- | --- | --- | | apiKey | string | – | Source-bunden API-nyckel (obligatorisk) | | baseUrl | string | produktionsinstansen | Bas-URL | | validate | boolean | true | Lokal zod-validering före sändning | | maxRetries | number | 3 | Omförsök vid nätverksfel/5xx/429 | | baseDelayMs | number | 500 | Bas för exponentiell backoff | | fetchFn | typeof fetch | global fetch | Egen fetch (t.ex. vid test) | | idempotencyKey | (payload) => string | auto | Egen nyckelgenerator |

client.submitLead(payload, options?)

Returnerar Promise<SubmitResult> där status är "accepted" | "duplicate" | "rejected".

Release

Ändringar under packages/audiencemanager-js/ som når main triggar workflowen SDK auto bump and tag, som bumpa patch och publicerar till npm. Behandla merge till main som en avsiktlig SDK-release.

Krav

Node 18+ eller modern browser (global fetch och crypto.randomUUID).

Licens

MIT