# Ajouter Frak à un site internet personnalisé

# Ajouter Frak à un site internet personnalisé

Pour un site personnalisé, l'intégration de Frak se fait en deux étapes :

1. **Ajoutez les composants Frak à votre site.** Chargez Frak, définissez un objet de configuration et intégrez le bouton de partage, la bannière d'accueil ainsi que la carte post-achat. Choisissez ci-dessous la configuration qui correspond à votre environnement.
2. **Validez les achats depuis votre backend.** Confirmez les commandes réelles avec un webhook signé pour que les récompenses ne soient attribuées que lors de ventes authentiques.
**Avant de commencer:** Enregistrez d'abord votre site et ajoutez votre domaine dans le [tableau de bord business](https://business.frak.id/). Votre identifiant marchand sera ainsi résolu automatiquement à partir de votre domaine, ce qui permet de garder la configuration ci-dessous très courte. Voir [Enregistrer votre site](/guides/dashboard/register/).

## Les composants

Ces trois composants sont des [composants web](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) indépendants de tout framework. Ils fonctionnent donc de la même manière que vous écriviez du HTML brut, utilisiez un bundler ou construisiez votre site avec React.

| Composant | Emplacement | Action |
| --- | --- | --- |
| `<frak-button-share>` | Page produit, page d'accueil | Permet aux clients de partager votre boutique et de gagner des récompenses |
| `<frak-banner>` | Haut de la page | Accueille les visiteurs parrainés |
| `<frak-post-purchase>` | Page de confirmation de commande | Propose un partage juste après le paiement et suit la commande |

<Aside type="caution" title="Les noms d'attributs utilisent des tirets">
En HTML et JSX, les attributs composés de plusieurs mots doivent être écrits avec des tirets, et non en camelCase : utilisez `customer-id`, et non `customerId`. Les navigateurs convertissent les noms d'attributs en minuscules, un attribut en camelCase sera donc ignoré sans avertissement.
</Aside>

## 1. Ajoutez Frak à votre site

### Charger et configurer Frak

Ajoutez ceci dans le `<head>` de vos pages. L'objet de configuration est lu par Frak lors de son chargement, définissez-le donc **avant** la balise script.

```html title="index.html"
<head>
  <!-- 1. Configure Frak (domain defaults to the current host) -->
  <script>
    window.FrakSetup = {
      config: {
        metadata: {
          name: "Your Store",
          currency: "eur",
        },
      },
    };
  </script>

  <!-- 2. Avoid a flash of unstyled elements while the script loads -->
  <style>
    frak-button-share:not(:defined),
    frak-banner:not(:defined),
    frak-post-purchase:not(:defined) { display: none !important; }
  </style>

  <!-- 3. Load the components (auto-registers them and boots the SDK) -->
  <script
    type="module"
    src="https://cdn.jsdelivr.net/npm/@frak-labs/components@latest"
    defer="defer"
  ></script>
</head>
```

### Ajouter les composants

Placez la bannière près du haut de votre `<body>`, et le bouton de partage là où vous souhaitez que vos clients partagent :

```html
<body>
  <!-- Welcomes referred visitors -->
  <frak-banner></frak-banner>

  <!-- Inherits your theme's .button styles via classname -->
  <frak-button-share classname="button"></frak-button-share>
</body>
```

### Suivre l'achat

Sur votre page de confirmation de commande, ajoutez la carte post-achat avec les détails de votre commande. Lorsque `customer-id`, `order-id` et `token` sont tous présents, la carte enregistre également la commande automatiquement auprès de Frak :

```html
<frak-post-purchase
  customer-id="cust_123"
  order-id="order_456"
  token="a-unique-order-token"
></frak-post-purchase>
```

Si vous ne souhaitez pas afficher la carte, enregistrez plutôt la commande directement. L'action devient disponible dès que Frak est prêt :

```html
<script>
  window.addEventListener("frak:client", () => {
    window.FrakSetup.core.trackPurchaseStatus({
      customerId: "cust_123",
      orderId: "order_456",
      token: "a-unique-order-token",
    });
  });
</script>
```

### Installation

```bash
npm install @frak-labs/components @frak-labs/core-sdk
```

### Configurer Frak

Définissez la configuration dans son propre module afin qu'elle s'exécute en premier :

```ts title="frak-setup.ts"
import type { FrakWalletSdkConfig } from "@frak-labs/core-sdk";

declare global {
  interface Window {
    FrakSetup: { config?: FrakWalletSdkConfig };
  }
}

window.FrakSetup = {
  config: {
    metadata: {
      name: "Your Store",
      currency: "eur",
    },
  },
};
```

### Enregistrer les composants

Importez d'abord votre module de configuration, puis importez chaque composant que vous utilisez. L'importation d'un composant enregistre son élément personnalisé et démarre le SDK depuis `window.FrakSetup.config` :

```ts title="main.ts"
import "./frak-setup";
import "@frak-labs/components/banner";
import "@frak-labs/components/buttonShare";
import "@frak-labs/components/postPurchase";
```

Ajoutez ensuite les éléments dans votre code, exactement comme dans l'onglet HTML :

```html
<frak-banner></frak-banner>
<frak-button-share classname="button"></frak-button-share>
<frak-post-purchase
  customer-id="cust_123"
  order-id="order_456"
  token="a-unique-order-token"
></frak-post-purchase>
```

### Suivre l'achat

La carte post-achat suit automatiquement la commande lorsque les trois attributs sont fournis. Pour effectuer le suivi sans afficher la carte, appelez directement l'action :

```ts
import { trackPurchaseStatus } from "@frak-labs/core-sdk/actions";

await trackPurchaseStatus({
  customerId: "cust_123",
  orderId: "order_456",
  token: "a-unique-order-token",
});
```

Les composants visuels sont les mêmes composants web, utilisés à l'intérieur de JSX. Installez-les et, si vous le souhaitez, installez également `@frak-labs/core-sdk` pour les appels d'action directs :

```bash
npm install @frak-labs/components @frak-labs/core-sdk
```

### Configurer et enregistrer

Définissez la configuration dans son propre module, puis importez-la (ainsi que les composants) avant de générer le rendu de votre application :

```ts title="frak-setup.ts"
import type { FrakWalletSdkConfig } from "@frak-labs/core-sdk";

declare global {
  interface Window {
    FrakSetup: { config?: FrakWalletSdkConfig };
  }
}

window.FrakSetup = {
  config: {
    metadata: {
      name: "Your Store",
      currency: "eur",
    },
  },
};
```

```tsx title="main.tsx"
import "./frak-setup";
import "@frak-labs/components/banner";
import "@frak-labs/components/buttonShare";
import "@frak-labs/components/postPurchase";

import { createRoot } from "react-dom/client";
import { App } from "./App";

createRoot(document.getElementById("root")!).render(<App />);
```

### Utiliser les composants dans JSX

```tsx title="App.tsx"
export function App() {
  return (
    <>
      <frak-banner />
      <frak-button-share classname="button" />

      {/* On your order confirmation route */}
      <frak-post-purchase
        customer-id="cust_123"
        order-id="order_456"
        token="a-unique-order-token"
      />
    </>
  );
}
```

La carte post-achat suit automatiquement la commande. Pour effectuer le suivi sans la carte, appelez `trackPurchaseStatus` depuis `@frak-labs/core-sdk/actions` après la validation de la commande.
**TypeScript:** Il se peut que TypeScript ne reconnaisse pas les balises `<frak-*>` dans le JSX. Ajoutez une petite déclaration pour y remédier :

```ts title="frak.d.ts"
import type { HTMLAttributes } from "react";

declare global {
  namespace JSX {
    interface IntrinsicElements {
      "frak-banner": HTMLAttributes<HTMLElement>;
      "frak-button-share": HTMLAttributes<HTMLElement> & { classname?: string; text?: string };
      "frak-post-purchase": HTMLAttributes<HTMLElement> & {
        "customer-id"?: string;
        "order-id"?: string;
        token?: string;
      };
    }
  }
}
```

Sur React 19, déclarez le même `namespace JSX` dans `declare module "react"` plutôt que dans `declare global`.

<Aside type="note" title="Besoin d'un contrôle programmatique ?">
Pour les parcours personnalisés (statut du portefeuille, hooks de parrainage, ouverture manuelle de la modale), `@frak-labs/react-sdk` propose des hooks et des providers React. Voir le [guide d'intégration React](/developers/integration/react/).
</Aside>
**Toutes les options:** La liste complète des attributs de chaque composant se trouve dans la documentation développeur : [bouton de partage](/developers/components/share-button/), [bannière](/developers/components/banner/), [post-achat](/developers/components/post-purchase/) et [configuration `FrakSetup`](/developers/components/frak-setup/).

## 2. Validez les achats depuis votre backend

Le suivi sur la page indique à Frak qu'une commande *pourrait* être en cours. Les récompenses ne sont déclenchées que lorsque votre backend confirme que la commande est réelle à l'aide d'un webhook signé. Cela permet de garantir que les récompenses sont associées à des ventes réelles et payées.

1. **La page enregistre la commande.** La carte post-achat (ou `trackPurchaseStatus`) envoie `customerId`, `orderId` et `token` pour que Frak commence à écouter cette commande.

2. **Votre backend la confirme.** Lorsque la commande est payée (ou remboursée, annulée), votre serveur envoie un webhook à Frak avec les mêmes identifiants et une signature HMAC.

3. **Frak déclenche la récompense.** Dès que la signature est validée et que le statut est `confirmed`, Frak envoie l'interaction `PurchaseCompleted`, ce qui permet de verser des récompenses en fonction de vos campagnes actives.

Votre URL de webhook et votre secret de signature se trouvent dans le [tableau de bord business](https://business.frak.id/), dans la section **Suivi des achats** de votre espace marchand. Signez l'intégralité du corps de la requête avec HMAC SHA-256 et envoyez-la dans l'en-tête `x-hmac-sha256`.

```ts
import crypto from "node:crypto";

async function sendPurchaseWebhook(order: {
  id: string;
  customerId: string;
  status: "pending" | "confirmed" | "cancelled" | "refunded";
  token: string;
  currency?: string;
  totalPrice?: string;
}) {
  const body = JSON.stringify(order);
  const hmac = crypto
    .createHmac("sha256", process.env.FRAK_WEBHOOK_SECRET)
    .update(body)
    .digest("hex");

  await fetch(process.env.FRAK_WEBHOOK_URL, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-hmac-sha256": hmac,
      // Use "true" while testing, "false" in production
      "x-test": "false",
    },
    body,
  });
}

await sendPurchaseWebhook({
  id: "order_456",
  customerId: "cust_123",
  status: "confirmed",
  token: "a-unique-order-token",
  currency: "EUR",
  totalPrice: "99.99",
});
```

```php
function sendPurchaseWebhook(array $order): void {
    $url = getenv('FRAK_WEBHOOK_URL');
    $secret = getenv('FRAK_WEBHOOK_SECRET');

    $body = json_encode($order);
    $hmac = hash_hmac('sha256', $body, $secret);

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $body,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'x-hmac-sha256: ' . $hmac,
            'x-test: false', // "true" while testing
        ],
    ]);
    curl_exec($ch);
    curl_close($ch);
}

sendPurchaseWebhook([
    'id' => 'order_456',
    'customerId' => 'cust_123',
    'status' => 'confirmed',
    'token' => 'a-unique-order-token',
    'currency' => 'EUR',
    'totalPrice' => '99.99',
]);
```
**Les identifiants doivent correspondre:** La valeur de `id` du webhook doit être identique à celle de `order-id` sur la page, et `customerId` et `token` doivent correspondre aux valeurs envoyées lors du suivi. S'ils diffèrent, Frak ne pourra pas lier la confirmation à la commande et aucune récompense ne sera déclenchée.

Consultez la [référence du webhook d'achat](/developers/api/webhook/) pour obtenir la charge utile complète (y compris les articles de la commande) et l'endpoint [suivi d'achat](/developers/api/track-purchase/) pour l'appel côté page.

## Étapes suivantes

[Ajouter des fonds](/guides/dashboard/configure/funds/)
  [Créer une campagne](/guides/campaigns/create/)
  [Référence des composants](/developers/components/)
  [Guide Vanilla JS / CDN](/developers/integration/cdn/)