Le parcours navigateur simple n'utilise pas de clé secrète RefCampaign. Installez le script CDN avec votre site token public, vérifiez la capture de session dans le dashboard, puis appelez éventuellement `identify()` après inscription ou connexion.

Le paquet [`@refcampaign/sdk`](https://www.npmjs.com/package/@refcampaign/sdk) expose deux clients :

* `RefCampaignBrowser` capture la session d'affiliation dans le navigateur et peut associer un hash email après inscription ou connexion.
* `RefCampaignServer` envoie des conversions manuelles depuis votre backend. Il nécessite votre clé secrète et n'est pas nécessaire pour le SDK navigateur simple ni pour le handoff metadata Stripe.

## Démarrage rapide

<Steps>
  <Step>
    ### Ajouter la capture navigateur

    Pour les sites no-code, sites simples ou frontends SaaS où vous ne voulez pas ajouter une dépendance au bundle, collez le script CDN dans votre `<head>` :

    ```html
    <script src="https://sdk.refcampaign.com/v1.js?s=rcst_PUBLIC_SITE_TOKEN" async></script>
    ```

    Le script capture la session depuis l'URL, le cookie ou le local storage, puis expose `window.RefCampaignBrowser`.
  </Step>

  <Step>
    ### Ajouter les metadata Stripe à la création du paiement

    Lisez la session navigateur RefCampaign et transmettez-la à Stripe comme metadata `refcampaign_session`.

    ```ts
    const sessionId = /* lire _rc_sid depuis le cookie de requête ou le payload checkout */
    const metadata = sessionId ? { refcampaign_session: sessionId } : {}
    ```

    Cette étape d'attribution Stripe ne nécessite pas de clé secrète RefCampaign.
  </Step>
</Steps>

## Choisir un chemin d'installation

### Script CDN

Utilisez ce chemin pour Webflow, Framer, WordPress, Wix, HTML statique ou tout site qui permet de coller du code personnalisé :

```html
<script src="https://sdk.refcampaign.com/v1.js?s=rcst_PUBLIC_SITE_TOKEN" async></script>
```

Cela capture les clics et les sessions. L'attribution des conversions Stripe nécessite seulement que votre backend transmette la metadata `refcampaign_session` à Stripe.

### CDN navigateur + handoff metadata Stripe

C'est l'installation SaaS recommandée : gardez la capture navigateur sur le CDN et ajoutez l'identifiant de session aux metadata Stripe depuis votre backend.

```ts
const sessionId = req.cookies.get('_rc_sid')?.value
const metadata = sessionId ? { refcampaign_session: sessionId } : {}
```

### npm complet

Utilisez la capture navigateur npm si vous préférez garder le SDK navigateur dans le bundle de votre application :

```ts
import { RefCampaignBrowser } from '@refcampaign/sdk'

RefCampaignBrowser.configure({
  siteToken: 'rcst_PUBLIC_SITE_TOKEN',
})

RefCampaignBrowser.captureSession()
```

Choisissez un seul chemin navigateur : le script CDN ou `RefCampaignBrowser.captureSession()` depuis npm. La clé secrète RefCampaign est requise uniquement quand vous branchez des conversions manuelles backend.

## Attribution Stripe

### Checkout Sessions

Pour les abonnements Stripe Checkout, ajoutez les metadata à la Checkout Session et à `subscription_data` afin que les factures récurrentes conservent l'attribution :

```ts
import Stripe from 'stripe'

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)

export async function POST(req: Request) {
  const { priceId, sessionId } = await req.json()
  const metadata = sessionId ? { refcampaign_session: sessionId } : {}

  const checkout = await stripe.checkout.sessions.create({
    line_items: [{ price: priceId, quantity: 1 }],
    mode: 'subscription',
    metadata,
    subscription_data: { metadata },
    success_url: 'https://yoursite.com/success',
    cancel_url: 'https://yoursite.com/cancel',
  })

  return Response.json({ url: checkout.url })
}
```

### Paiements ponctuels

Pour les paiements ponctuels, placez les metadata sur le Payment Intent :

```ts
await stripe.paymentIntents.create({
  amount: 4900,
  currency: 'eur',
  metadata: sessionId ? { refcampaign_session: sessionId } : {},
})
```

### Abonnements directs

Pour la création directe d'abonnements, placez les metadata sur la Subscription :

```ts
await stripe.subscriptions.create({
  customer: customer.id,
  items: [{ price: 'price_xxx' }],
  metadata: sessionId ? { refcampaign_session: sessionId } : {},
})
```

## Identifier les clients

Appelez `identify()` après connexion ou inscription pour améliorer l'attribution quand les cookies sont perdus, que Safari ITP expire le stockage, ou que le client convertit sur un autre appareil.

```ts
import { RefCampaignBrowser } from '@refcampaign/sdk'

RefCampaignBrowser.identify(currentUser.email)
```

Le SDK navigateur hash l'email côté client en SHA-256 avant de l'envoyer à RefCampaign.

## Suivi manuel des conversions

Pour les paiements hors Stripe, envoyez la conversion depuis votre backend :

```ts
import { RefCampaignServer } from '@refcampaign/sdk'

const rc = new RefCampaignServer(process.env.REFCAMPAIGN_SECRET_KEY!, {
  onError(error, context) {
    console.error('RefCampaign conversion failed', { error, ...context })
  },
})

const health = await rc.verify()
if (!health.valid) {
  console.error(health.reason)
}

const result = await rc.trackConversion({
  orderId: 'ord_42',
  sessionId,
  amount: 4900,
  currency: 'EUR',
  metadata: { payment_method: 'paypal' },
})

if (!result.success) {
  console.error(result.error)
}
```

Les montants sont des centimes entiers. `orderId` est requis et sert de clé d'idempotence. Utilisez le `sessionId` depuis le cookie de session du SDK navigateur, le local storage ou votre propre payload checkout. Si votre checkout stocke déjà le code partenaire, envoyez `affiliateCode`; si les cookies ont disparu après `identify()`, envoyez `customerEmailHash`.

Le client serveur expose `verify()` pour les checks de santé. `onError` reçoit `{ orderId, attempts, operation }`, où `operation` vaut `track` ou `refund`.

## Rembourser une conversion

Quand un client est remboursé, annulez la conversion et reprenez la commission affiliée. Transmettez le même `orderId` que lors du tracking :

```ts
import { RefCampaignServer } from '@refcampaign/sdk'

const rc = new RefCampaignServer(process.env.REFCAMPAIGN_SECRET_KEY!)

// Remboursement complet
await rc.refundConversion({ orderId: 'ord_42' })

// Remboursement partiel de 10,00 € avec une raison
const result = await rc.refundConversion({
  orderId: 'ord_42',
  amount: 1000,
  reason: 'partial return',
})

if (result.alreadyRefunded) {
  // Idempotent : cette conversion était déjà remboursée.
}
```

L'appel est idempotent sur `orderId` : un remboursement répété retourne `alreadyRefunded: true`. Seules les conversions `APPROVED` sont remboursables; les remboursements partiels reprennent la commission au prorata. Voir le [guide postback](/fr/docs/api/integration/postback#rembourser-une-conversion) pour le contrat REST sous-jacent.

## Staging

Le SDK navigateur pointe par défaut vers `https://app.refcampaign.com`. Surchargez cette URL avant `identify()` quand vous testez contre staging :

```ts
import { RefCampaignBrowser } from '@refcampaign/sdk'

RefCampaignBrowser.configure({
  apiBase: 'https://app.test.refcampaign.com',
  siteToken: 'rcst_PUBLIC_SITE_TOKEN',
  debug: true,
})
```

Pour les conversions manuelles backend, le SDK serveur utilise `apiUrl` :

```ts
const rc = new RefCampaignServer(process.env.REFCAMPAIGN_SECRET_KEY!, {
  apiUrl: 'https://app.test.refcampaign.com',
})
```

## Alternative REST pure

Si vous ne pouvez pas ajouter de dépendance, appelez directement les endpoints. Voir [postback serveur à serveur](/fr/docs/api/integration/postback).
