This is the full developer documentation for Wallet SDK by Frak # Wallet SDK by Frak > Seamlessly integrate Web3 functionality into your applications with user-friendly wallet interactions, engagement tracking, and reward systems. import IntegrationCards from "@/components/IntegrationCards.astro"; ## Key Features - Seamless on-chain user interactions - Delegated sessions for gas-less transactions - Customizable reward and referral systems - React and vanilla JavaScript support - Sign-In with Ethereum (SIWE) authentication ## Demos - [JS SDK Integration](https://vanilla.frak-labs.com/): Very simple example with modals, interactions, and more. ## Community - Twitter: [@frak_defi](https://twitter.com/frak_defi) - Team: [@srod](https://twitter.com/srod), [@MViala](https://twitter.com/MViala), [@VirginieMaire](https://twitter.com/VirginieMaire), [@qnivelais](https://twitter.com/QNivelais) - [Medium](https://medium.com/frak-defi) - [GitHub](https://github.com/frak-id/wallet) Join us in revolutionizing digital content engagement with Web3! # Wallet SDK > Seamless Web3 interactions for your applications # Overview Welcome to the Wallet SDK documentation! The Wallet SDK provides developers with powerful tools to integrate seamless Web3 interactions into their applications, leveraging the user-friendly Frak Wallet. ## Frak Wallet The Frak Wallet is a cutting-edge cryptocurrency wallet designed with a strong emphasis on user experience. Built using the latest technologies, including [Account Abstraction](https://eips.ethereum.org/EIPS/eip-4337) and [WebAuthn](https://w3c.github.io/webauthn/), the Frak Wallet simplifies the onboarding process and enhances Web3 interactions. ![The Frak Wallet running on a mobile phone](/img/wallet/wallet-on-phone.webp) With the Frak Wallet, users can create an account using biometric authentication (fingerprint, facial recognition, etc.) and then seamlessly interact with decentralized applications (dApps). It eliminates the need for recovery phrases, pre-funded wallets for gas fees, and clunky browser extensions, providing a smooth and intuitive experience. The Frak Wallet is fully compatible with the WalletConnect standard, ensuring compatibility with a wide range of dApps and Web3 services. ## Wallet SDK The Wallet SDK is designed to streamline the integration of Web3 interactions into your applications, providing a comprehensive set of tools and features for various use cases. ### Key Features 1. **Seamless User Interactions**: Easily trigger on-chain events based on user actions within your application. 2. **Delegated User Sessions**: Implement gas-less transactions for your users, improving their experience. 3. **Reward Systems**: Set up and manage reward campaigns based on user interactions. 4. **Referral Tracking**: Implement and track referral-based campaigns with automatic reward distribution. 5. **Flexible Integration**: Works with both React and vanilla JavaScript applications. 6. **Advanced Authentication**: Utilize Sign-In with Ethereum (SIWE) for secure, blockchain-based authentication. ### Use Cases #### For Content Platforms - **Engagement Tracking**: Record on-chain interactions when users engage with your content. - **Reward Programs**: Automatically distribute rewards (tokens, NFTs, etc.) based on user engagement. - **Referral Systems**: Implement blockchain-based referral programs, rewarding users for sharing your platform. - **Community Building**: Use on-chain interactions to build a verifiable community around your content. #### For dApp Developers - **Smooth Onboarding**: Leverage Account Abstraction for a frictionless user onboarding experience. - **Gasless Transactions**: Optionally cover gas fees for your users, reducing barriers to interaction. - **Interaction Tracking**: Record user interactions on-chain for transparent and verifiable user activity. - **Custom Reward Mechanisms**: Implement token or NFT-based rewards tied directly to in-app actions. ### Integration Benefits By integrating the Wallet SDK, you can: 1. **Enhance User Experience**: Provide a seamless Web3 experience without the typical blockchain complexities. 2. **Increase Engagement**: Implement reward systems that encourage user participation and sharing. 3. **Build Trust**: Utilize blockchain technology for transparent and verifiable user interactions. 4. **Flexible Implementation**: Easily incorporate Wallet SDK into your existing Web3 setup, compatible with popular libraries like Wagmi. 5. **Future-Proof**: Stay ahead with the latest in blockchain technology, including Account Abstraction and WebAuthn. The Wallet SDK empowers you to create decentralized, trustless, and user-friendly experiences while leveraging cutting-edge blockchain technologies. Whether you're building a content platform, a dApp, or any Web3-enabled application, the Wallet SDK provides the tools you need to implement robust, blockchain-based user interactions and reward systems. # Track Purchase Endpoint > API endpoint to register a purchase event for tracking # Track Purchase Endpoint ## Summary The track purchase endpoint registers a purchase event so the Frak backend can send `PurchaseCompleted` interactions automatically once the purchase is confirmed via webhook. ## Requirements - At least one identity source: a Frak Wallet session (`x-wallet-sdk-auth`) **or** a client id (`x-frak-client-id`). Anonymous users are supported. - A `merchantId` — resolved explicitly, from session storage, or via the merchant lookup API. - Purchase details: `customerId`, `orderId`, and `token`. ## Endpoint ```http POST /user/track/purchase ``` ### Headers - `Accept`: `application/json` - `Content-Type`: `application/json` - `x-wallet-sdk-auth` (optional): JWT token from the user SDK session. Obtain via [`watchWalletStatus`](/developers/references/core-sdk/actions/functions/watchwalletstatus/) (`status.interactionToken`). - `x-frak-client-id` (optional): Unique client identifier for anonymous user tracking. At least one of `x-wallet-sdk-auth` or `x-frak-client-id` must be present. ### Request Body The request body should be a JSON object with the following properties: - `customerId` (`string | number`): The ID of the customer making the purchase. Should match the value sent during purchase validation. - `orderId` (`string | number`): The ID of the order being placed. Should match the value sent during purchase validation. - `token` (`string`): A unique token related to the purchase. - `merchantId` (`string`): The merchant identifier. Resolved from the explicit parameter, `frak-merchant-id` in session storage, or the merchant lookup API. #### Example Request Body ```json { "customerId": "123456", "orderId": "987654", "token": "unique-token-value", "merchantId": "your-merchant-id" } ``` ## Usage Example Using the SDK (recommended): ```js import { trackPurchaseStatus } from "@frak-labs/core-sdk/actions"; await trackPurchaseStatus({ customerId: checkout.order.customer.id, orderId: checkout.order.id, token: checkout.token, merchantId: "your-merchant-id", }); ``` Direct `fetch` call: ```js const interactionToken = window.sessionStorage.getItem("frak-wallet-interaction-token"); const clientId = localStorage.getItem("frak-client-id"); const headers = { 'Accept': 'application/json', 'Content-Type': 'application/json', }; if (interactionToken) headers['x-wallet-sdk-auth'] = interactionToken; if (clientId) headers['x-frak-client-id'] = clientId; const payload = { customerId: checkout.order.customer.id, orderId: checkout.order.id, token: checkout.token, merchantId: "your-merchant-id", }; fetch('https://backend.frak.id/user/track/purchase', { method: 'POST', headers, body: JSON.stringify(payload), }); ``` ## Response The endpoint responds with an acknowledgment of whether the purchase registration was successful. ## Related SDK Method - [`trackPurchaseStatus`](/developers/references/core-sdk/actions/functions/trackpurchasestatus/) — wrapper around this endpoint with automatic merchant id resolution and identity header management. ## Notes - `merchantId` is required. The SDK resolves it automatically from: explicit param → `frak-merchant-id` in session storage → backend lookup. - At least one identity header (`x-wallet-sdk-auth` or `x-frak-client-id`) must be present. The SDK skips the request if neither is available. - Ensure `customerId`, `orderId`, and `token` values match between the client and the purchase validation webhooks. # Purchase Webhooks > API webhooks to track and validate purchase events import { Tabs, TabItem } from "@astrojs/starlight/components"; # Purchase Webhooks ## Summary The purchase webhooks allow your application to validate purchase events and automatically trigger the `PurchaseCompleted` interaction, which could potentially lead to user rewards based on active campaigns. The webhooks also update the on-chain purchase oracle for your merchant, allowing you to know whether a purchase has been finalized. All purchase data is anonymized, and the oracle is updated with a Merkle tree root where each leaf contains a hashed `purchaseId`, `userId`, and the purchase finality status. ## Available Webhooks We provide three types of webhooks to handle purchase tracking: 1. **Shopify Webhook** 2. **WooCommerce Webhook** 3. **Custom Webhook** ### Shopify Webhook The Shopify webhook should be set up to trigger on order updates, allowing the backend to validate purchases and update the oracle. It is provisioned automatically by the official Frak Shopify app during onboarding — see the [Shopify Integration Guide](/guides/shopify) for details. ### WooCommerce Webhook Similar to the Shopify webhook, the WooCommerce webhook is provisioned automatically by the Frak WordPress plugin once the webhook secret is pasted in. Follow the [WordPress integration guide](/guides/platforms/wordpress/details/#order-tracking-with-woocommerce) to properly set it up. ### Custom Webhook The Custom webhook is designed for applications that use a custom eCommerce solution or need more flexibility. This webhook requires specific headers and a payload to register the purchase event. #### Endpoint The specific endpoint URL for each webhook type is visible in the business dashboard under the `Purchase Tracker` section of your merchant. #### Headers - **`x-hmac-sha256`**: A HMAC SHA-256 digest of the entire request body. The HMAC is computed using the secret available in your business dashboard. - **`x-test`**: Indicates if the webhook call is for a test order. This is useful for development environments. #### Request Body The body of the Custom webhook should be a JSON object that follows the `CustomWebhookDto` type: ```ts type CustomWebhookDto = Readonly<{ /** * Id of the order on your side (external order id) */ id: string; /** * Id of the customer on your side (external customer id) */ customerId: string; /** * Status of the order */ status: "pending" | "confirmed" | "cancelled" | "refunded"; /** * Custom token for this order * - Should be the same one as the one exposed to the end user and submitted through the `listenForPurchase` API method */ token: string; /** * Currency code (ISO 4217) * - Optional, could be empty * - Recommended for the UX in the members space */ currency?: string; /** * The total price of the order, in the currency provided * - Optional, could be empty * - Recommended for the UX in the members space */ totalPrice?: string; /** * All the items in the order * - Optional * - Will be used in the wallet members space, to display additional data to the end user, e.g. which product they referee bought the most */ items?: { /** * The product id on your side */ productId: string; /** * The quantity of the product in the order */ quantity: number; /** * The price of the product */ price: string; /** * An internal name for the product, used in url slug */ name: string; /** * The displayable title of the product */ title: string; /** * A potential image URL for the product */ image?: string; }[]; }>; ``` ### Example Here is a few custom webhook calls in different languages: ```ts import crypto from 'crypto'; type Purchase = { id: string; customerId: string; status: "pending" | "confirmed" | "cancelled" | "refunded"; token: string; currency?: string; totalPrice?: string; items?: { productId: string; quantity: number; price: string; name: string; title: string; image?: string; }[]; } async function sendPurchaseWebhook( purchase: Purchase ): Promise { const body = JSON.stringify(purchase); const hmac = await crypto .createHmac('sha256', process.env.FRAK_PURCHASE_WEBHOOK_SECRET) .update(body) .digest('hex'); await fetch(process.env.FRAK_PURCHASE_WEBHOOK, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-hmac-sha256': hmac, 'x-test': process.env.NODE_ENV === 'production' ? 'false' : 'true' }, body }); } // Usage example const purchase = { id: 'order_123', customerId: 'cust_456', status: 'confirmed', token: 'purchase_token_789', currency: 'USD', totalPrice: '99.99', items: [{ productId: 'prod_001', quantity: 1, price: '99.99', name: 'premium-subscription', title: 'Premium Subscription' }] }; sendPurchaseWebhook(purchase) .then(response => console.log('Webhook sent successfully:', response)) .catch(error => console.error('Error sending webhook:', error)); ``` ```php function sendPurchaseWebhook(array $purchase): void { $webhookUrl = 'your_webhook_url_from_dashboard'; $secretKey = 'your_secret_key_from_dashboard'; $isTest = true; // Set to false in production $body = json_encode($purchase); $hmac = hash_hmac('sha256', $body, $secretKey); $ch = curl_init($webhookUrl); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $body, CURLOPT_RETURNTRANSFER => false, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'x-hmac-sha256: ' . $hmac, 'x-test: ' . ($isTest ? 'true' : 'false') ] ]); curl_exec($ch); curl_close($ch); } // Usage example $purchase = [ 'id' => 'order_123', 'customerId' => 'cust_456', 'status' => 'confirmed', 'token' => 'purchase_token_789', 'currency' => 'USD', 'totalPrice' => '99.99', 'items' => [ [ 'productId' => 'prod_001', 'quantity' => 1, 'price' => '99.99', 'name' => 'premium-subscription', 'title' => 'Premium Subscription' ] ] ]; sendPurchaseWebhook($purchase); ``` ## HMAC Signature Each webhook request should include a valid HMAC signature of the entire body payload, ensuring the request's integrity and authenticity. The secret used to generate this HMAC signature is available in your business dashboard. ## Response All webhook types expect a JSON response indicating whether the request was successfully processed. ## Notes - Ensure that the `id`, `customerId`, `status`, and `token` fields are consistent between the client and the server to ensure successful tracking. - The webhooks automatically update the on-chain purchase oracle, which anonymously tracks the purchase finality status. - You can find the specific webhook URL for your merchant in the business dashboard, under the `Purchase Tracker` section of your merchant. # Getting Started with Frak Components > Learn how to set up and start using Frak Components in your project # Getting Started with Frak Components This guide will walk you through the process of setting up and using Frak Components in your project. You can find examples of Frak Components at [https://showcase.frak.id/](https://showcase.frak.id/). ## Prerequisites Before you begin, ensure you have: - A modern web browser - Basic knowledge of HTML and JavaScript ## 1. Register Your Merchant :::note Merchant registration is a crucial step that enables key functionalities of Frak Components. ::: Before using Frak Components, you need a merchant account on the Frak Business Platform: 1. Visit [https://business.frak.id/](https://business.frak.id/) 2. Sign up or log in to your account — your main storefront domain is registered automatically at sign-up. 3. (Optional) If your site lives on a subdomain different from the registered main domain, add it under **Allowed Domains** on the dashboard. For a detailed walkthrough, see our [Business Registration Guide](/guides/dashboard/register/). ## 2. Setup the Frak Components Once your merchant is set up, install Frak Components in your project. Add the following script tag to your HTML file: ```html ``` ## 3. Basic Configuration After setup, you need to add a `config` object by assigning a global variable `FrakSetup`. You can generate a config object using the [Frak SDK Builder](https://showcase.frak.id/configuration). ```html ``` More information about the [FrakSetup](/developers/components/frak-setup) object. ## 4. Add Components Now you can start adding Frak Components to your project. Here's an example of how to add a share button: ```html ``` That's it! You've successfully set up and started using Frak Components in your project. ## Next Steps Now that you're set up, you can explore components and customize them to fit your project requirements: - [Share Button](/developers/components/share-button) - [Banner](/developers/components/banner) - [Post-Purchase](/developers/components/post-purchase) - [Open In App](/developers/components/open-in-app) - [FrakSetup Configuration](/developers/components/frak-setup) You can also explore our [Wallet SDK](/developers) documentation for more advanced features and customization options. # Banner Component > Display referral and in-app browser banners on your website # Banner ## Summary The `` component displays contextual banners on your website. It automatically detects the user's context and shows one of two variants: - **Referral banner** — Promotes sharing and rewards to eligible users. - **In-app browser banner** — Prompts users browsing in an in-app browser (Instagram, TikTok, etc.) to open the page in their default browser for a better experience. This variant is opt-in: enable it with the `allowInappRedirect` attribute. ## Requirements - An initialized `FrakSetup` configuration object More information about the [FrakSetup](/developers/components/frak-setup) object. ## Parameters | Attribute | Type | Description | |-----------|------|-------------| | `placement` | `string` | Placement ID for [backend-driven configuration](/developers/concepts/placements). | | `classname` | `string` | CSS class names applied to the root element. | | `interaction` | `string` | Filter rewards by interaction type (e.g. `"purchase"`, `"referral"`). When omitted, the best reward across all types is shown. | | `referralTitle` | `string` | Override the referral banner title. | | `referralDescription` | `string` | Override the referral banner description. | | `referralCta` | `string` | Override the referral banner CTA button text. | | `inappTitle` | `string` | Override the in-app browser banner title. | | `inappDescription` | `string` | Override the in-app browser banner description. | | `inappCta` | `string` | Override the in-app browser banner CTA button text. | | `imageUrl` | `string` | Override the image shown on the left of the referral banner. Falls back to the built-in gift icon when omitted. | | `preview` | `string` | When set, forces the banner to render in preview mode (e.g. in Shopify theme editor). | | `previewMode` | `"referral"` \| `"inapp"` | Which variant to preview. Only used when `preview` is set. Defaults to `"referral"`. | | `allowInappRedirect` | `boolean` \| `"true"` \| `"false"` | Allow the banner to switch to in-app browser mode and prompt users to open the system browser. Opt-in, defaults to `false`. | ## Usage Examples ### Basic Banner ```html ``` ### With Custom Referral Text ```html ``` ### With In-App Browser Text ```html ``` ### With Placement ```html ``` Banner text and styling are resolved from the [placement configuration](/developers/concepts/placements) set in the business dashboard. ### With Custom Class ```html ``` ### Preview Mode (Theme Editors) When building a theme editor integration (e.g. Shopify), use `preview` to render static content without requiring an active SDK connection: ```html ``` ## CSS Target the component using the `frak-banner` selector: ```css frak-banner .override { background-color: #f5f5f5; border-radius: 8px; } ``` Component-specific CSS can also be configured via [placements](/developers/concepts/placements) in the business dashboard. # FrakSetup object > Learn how to configure the Frak Setup object in your project # `FrakSetup` object The `FrakSetup` object is used to configure the Frak Components library in your project. It allows you to set up metadata and other configuration options for your application. It is required to initialize the Frak Components library and should be passed as a global variable in your project. You can generate a config object using the [Frak SDK Builder](https://showcase.frak.id/configuration). ## `config` object The `config` object is used to configure the Frak Components library. It allows you to set up metadata about your application, such as the name and CSS styles. ```ts twoslash title="TypeScript" // @noErrors // [!include ~/snippets/types/FrakWalletSdkConfig.ts] window.FrakSetup = { config: FrakWalletSdkConfig; } ``` ### Example ```js twoslash title="JavaScript" window.FrakSetup = { config: { walletUrl: "https://wallet.frak.id", metadata: { name: "My Awesome dApp", merchantId: "550e8400-e29b-41d4-a716-446655440000", lang: "fr", currency: "eur" }, customizations: { css: "https://my-app.com/frak-styles.css", }, domain: "my-app.com" }, }; ``` For more detailed `config` options, see our [FrakWalletSdkConfig](/developers/references/core-sdk/index/type-aliases/frakwalletsdkconfig/). ## `modalWalletConfig` object The `modalWalletConfig` object is used to configure the embedded wallet displayed by the Frak Components. It allows you to customize the wallet appearance, sharing behavior, and logged-out state. ```ts twoslash title="TypeScript" // @noErrors import type { DisplayEmbeddedWalletParamsType } from '@frak-labs/core-sdk'; // [!code focus] window.FrakSetup = { // [!code focus] config: { /* ... */ }, modalWalletConfig: DisplayEmbeddedWalletParamsType; // [!code focus] } // [!code focus] ``` The `DisplayEmbeddedWalletParamsType` has the following properties: | Parameter | Type | Description | | --------- | ---- | ----------- | | `loggedIn` | `object` | Configuration for the wallet view when user is logged in | | `loggedIn.action` | `object` | The main action to display. Set `key: "sharing"` for a share button, or `key: "referred"` for a referred state | | `loggedIn.action.options.link` | `string` | The link to be shared (suffixed with Frak sharing context). Only for `key: "sharing"` | | `loggedOut` | `object` | Configuration for the wallet view when user is logged out | | `metadata` | `object` | Metadata to customize the embedded wallet | | `metadata.logo` | `string` | Logo URL displayed on the embedded wallet | | `metadata.homepageLink` | `string` | Link to the homepage of the calling website | | `metadata.targetInteraction` | `string` | The target interaction behind this modal | | `metadata.position` | `"left" \| "right"` | Position of the wallet component | | `metadata.i18n` | `I18nConfig` | i18n overrides for the embedded wallet text | ### Example ```js twoslash title="JavaScript" window.FrakSetup = { config: { metadata: { name: "My Awesome dApp", }, }, modalWalletConfig: { // [!code focus] loggedIn: { // [!code focus] action: { // [!code focus] key: "sharing", // [!code focus] options: { // [!code focus] link: "https://my-app.com", // [!code focus] }, // [!code focus] }, // [!code focus] }, // [!code focus] metadata: { // [!code focus] logo: "https://my-app.com/logo.png", // [!code focus] homepageLink: "https://my-app.com", // [!code focus] position: "right", // [!code focus] i18n: { // [!code focus] "sharing.text": "Check out my app!", // [!code focus] }, // [!code focus] }, // [!code focus] }, // [!code focus] }; # Open In App Component > Redirect users from in-app browsers to the system browser # Open In App ## Summary The `` component renders a button that redirects users from in-app browsers (Instagram, TikTok, Facebook, etc.) to the device's default browser. This ensures a better user experience for features like WebAuthn authentication that don't work well in WebViews. :::note This component only renders on mobile devices. On desktop, it returns nothing. ::: ## Requirements - An initialized `FrakSetup` configuration object More information about the [FrakSetup](/developers/components/frak-setup) object. ## Parameters | Attribute | Type | Default | Description | |-----------|------|---------|-------------| | `text` | `string` | `"Open in App"` | Text to display on the button. | | `placement` | `string` | — | Placement ID for [backend-driven configuration](/developers/concepts/placements). | | `classname` | `string` | — | CSS class names applied to the root element. | ## Usage Examples ### Basic Button ```html ``` ### With Custom Text ```html ``` ### With Placement ```html ``` ### With Custom Class ```html ``` ## CSS Target the component using the `frak-open-in-app` selector: ```css frak-open-in-app .override { background-color: #1a1a1a; color: #fff; border-radius: 8px; } ``` Component-specific CSS can also be configured via [placements](/developers/concepts/placements) in the business dashboard. # Post-Purchase Component > Display a sharing prompt after a purchase to drive referrals # Post-Purchase ## Summary The `` component is designed for checkout confirmation pages. It displays a sharing prompt to buyers, encouraging them to share the product with friends. The component adapts its message based on whether the user is a **referrer** (existing advocate) or a **referee** (was referred by someone). ## Requirements - An initialized `FrakSetup` configuration object - Purchase tracking data (customer ID, order ID, and token) for attribution More information about the [FrakSetup](/developers/components/frak-setup) object. ## Parameters | Attribute | Type | Description | |-----------|------|-------------| | `customerId` | `string` | Merchant customer ID for purchase tracking. All three tracking props (`customerId`, `orderId`, `token`) must be present for tracking to fire. | | `orderId` | `string` | Merchant order ID for purchase tracking. | | `token` | `string` | Checkout token for purchase tracking. | | `sharingUrl` | `string` | Base URL to share. Falls back to the merchant domain when omitted. | | `merchantId` | `string` | Override the merchant ID resolved from SDK config. | | `placement` | `string` | Placement ID for [backend-driven configuration](/developers/concepts/placements). | | `classname` | `string` | CSS class names applied to the root element. | | `variant` | `"referrer"` \| `"referee"` | Force a display variant instead of relying on backend evaluation. | | `badgeText` | `string` | Label for the badge pill above the message. Hidden when omitted. | | `referrerText` | `string` | Override the message shown to referrers. Use `{REWARD}` as placeholder. | | `refereeText` | `string` | Override the message shown to referees. Use `{REWARD}` as placeholder. | | `ctaText` | `string` | Override the CTA button text. Use `{REWARD}` as placeholder. | | `imageUrl` | `string` | Override the image shown on the left of the card. Falls back to the built-in gift icon when omitted. | | `products` | `string` | JSON-stringified array of product cards forwarded to the sharing page when the CTA is clicked (set the JS `products` property for a real array). | | `preview` | `string` | Render in preview mode (e.g. Shopify/WordPress theme editor): bypasses the client-ready gate and no-ops the click handler. | | `previewVariant` | `"referrer"` \| `"referee"` | Which variant to show when `preview` is set. Defaults to `"referrer"`. | ## Usage Examples ### Basic Post-Purchase ```html ``` ### With Custom Text ```html ``` ### With Placement ```html ``` Text and styling are resolved from the [placement configuration](/developers/concepts/placements) set in the business dashboard. ### With Custom Sharing URL ```html ``` ### Force a Variant ```html ``` ## Purchase Tracking The component supports automatic purchase tracking when all three tracking attributes are provided: - `customerId` — Your internal customer identifier - `orderId` — The order/transaction identifier - `token` — A checkout token for verification :::tip All three attributes must be present for purchase tracking to fire. If any is missing, the component still renders the sharing prompt but doesn't track the purchase. ::: ## CSS Target the component using the `frak-post-purchase` selector: ```css frak-post-purchase .override { background-color: #f0fdf4; border-radius: 12px; padding: 24px; } ``` Component-specific CSS can also be configured via [placements](/developers/concepts/placements) in the business dashboard. # Share Button Component > Learn how to use the Share Button component in your web project # Share Button ## Summary The `` component opens a modal in the Frak Wallet interface with configurable steps, allowing for complex user interactions such as login, opening session and share. ## Requirements - An initialized `FrakSetup` configuration object More information about the [FrakSetup](/developers/components/frak-setup) object. ### Parameters | Attribute | Type | Default | Description | |-----------|------|---------|-------------| | `text` | `string` | `"Share and earn!"` | Text to display on the button. Include the `{REWARD}` placeholder to opt into the live reward flow (the SDK substitutes the estimated reward amount). | | `classname` | `string` | — | CSS class names applied to the button. | | `placement` | `string` | — | Placement ID for [backend-driven configuration](/developers/concepts/placements). | | `clickAction` | `"embedded-wallet"` \| `"sharing-page"` | `"sharing-page"` | Which UI to open when the button is clicked. Legacy values like `"share-modal"` are accepted at runtime and routed to the sharing page. | | `noRewardText` | `string` | — | Fallback text used when `text` contains `{REWARD}` but no reward is available. | | `targetInteraction` | `string` | — | Target interaction type used to calculate the displayed reward. | | `preview` | `string` | — | Render in preview mode (e.g. Shopify/WordPress theme editor): the button stays visually enabled and the click handler is a no-op. | ## Usage Examples ### Basic Share Button ```html ``` ### With Custom Text ```html ``` ### With Custom Class ```html ``` ### With Reward Display Include the `{REWARD}` placeholder in `text` to display the live estimated reward. Provide `noRewardText` as a fallback for when no reward is available. ```html ``` ### With Click Action Control which UI opens when the button is clicked: ```html ``` ### With Placement ```html ``` Button text, click action, and styling are resolved from the [placement configuration](/developers/concepts/placements) set in the business dashboard. HTML attributes override placement settings. ## CSS CSS can be used to style the button. Some default styles are applied to the button, but they can be overridden with custom CSS. Target the component using the `frak-button-share .override` selector. ```css frak-button-share .override { background-color: #000; color: #fff; } ``` Component-specific CSS can also be configured via [placements](/developers/concepts/placements) in the business dashboard. # Core Concepts of Wallet SDK > Understanding the fundamental concepts and components of the Wallet SDK # Core Concepts The Wallet SDK provides a powerful set of tools for integrating Web3 functionality into your applications. To effectively use the SDK, it's important to understand its core concepts. This section will introduce you to the key ideas behind the Wallet SDK. ## Key Concepts 1. [Configuration](/developers/concepts/configuration) Learn how to set up and customize the Wallet SDK for your specific needs. 2. [Interactions](/developers/concepts/interactions) Explore the concept of user interactions and how they form the basis of the Wallet SDK's functionality. 3. [Backend-Driven Configuration](/developers/concepts/backend-configuration) Learn how the SDK automatically resolves merchant configuration from the Frak backend. 4. [Placements](/developers/concepts/placements) Understand how to use placements to customize SDK behavior per page or section of your website. ## Understanding the Flow The Wallet SDK operates on a simple yet powerful flow: 1. **Configuration**: You set up the SDK with your specific parameters. 2. **Delegated Session**: A session is created, allowing for gasless transactions. 3. **User Interactions**: As users interact with your application, you track these interactions using the SDK. 4. **On-chain Recording**: These interactions are recorded on the blockchain, providing a transparent and verifiable record. 5. **Rewards and Campaigns**: Based on these interactions, you can trigger rewards or manage campaigns. ## Key Features - **Seamless Integration**: The SDK is designed to work smoothly with both React and vanilla JavaScript applications. - **Interaction Tracking**: Easily record user engagements and actions on the blockchain. - **Reward Systems**: Implement token or NFT-based reward programs tied to user interactions. - **Gasless Transactions**: Cover gas fees for your users, reducing barriers to interaction. - **Referral Programs**: Set up and manage blockchain-based referral systems. By understanding these core concepts, you'll be well-equipped to leverage the full power of the Wallet SDK in your applications. Dive into each concept to learn more about how they work and how to implement them in your projects. :::note For specific implementation details, please refer to the [Getting started](/guides) guides. ::: # Backend-Driven Configuration > Learn how the SDK dynamically resolves configuration from the Frak backend # Backend-Driven Configuration The Frak SDK supports dynamic configuration resolved from the backend. When your application initializes, the SDK fetches your merchant configuration from the Frak backend based on your domain. This means you can manage branding, translations, component settings, and [placements](/developers/concepts/placements) directly from the [business dashboard](/guides/dashboard) without redeploying your application. ## How It Works 1. **SDK Initialization** — When the SDK starts, it calls the Frak backend's resolve endpoint with your domain. 2. **Merchant Resolution** — The backend identifies your merchant account and returns the associated configuration. 3. **Config Merging** — The resolved backend config is merged with your local SDK config. Backend values take priority over local values. 4. **Reactive Updates** — Components automatically re-render when the backend configuration is resolved. ``` Your Website Frak Backend | | | GET /resolve?domain=... | |------------------------------>| | | | { merchantId, sdkConfig } | |<------------------------------| | | | Components update reactively | | | ``` ## Configuration Priority The SDK merges configuration from multiple sources. When the same setting exists at multiple levels, the highest-priority source wins: 1. **Backend config** (highest priority) — Set in the business dashboard 2. **SDK static config** — Passed in your `FrakWalletSdkConfig` object 3. **Defaults** — Built-in SDK defaults This means you can set sensible defaults in your code and override them from the dashboard without touching your codebase. ## Resolved Configuration The backend returns the following fields when available: | Field | Description | |-------|-------------| | `name` | Your application display name | | `logoUrl` | Logo URL displayed in modals and components | | `homepageLink` | Link to your homepage (used in some components) | | `currency` | Display currency (`"eur"`, `"usd"`, `"gbp"`) | | `lang` | Language override (`"en"`, `"fr"`) | | `hidden` | When `true`, all SDK components are hidden | | `css` | Global CSS applied to modals and components | | `translations` | Global translation overrides | | `placements` | Named placement configurations (see [Placements](/developers/concepts/placements)) | | `components` | Global component defaults | ## Controlling Loading Behavior By default, the SDK waits for the backend configuration to be resolved before rendering components. This ensures components display the correct branding and settings from the start. You can control this behavior with the `waitForBackendConfig` option: ```ts twoslash // @noErrors import type { FrakWalletSdkConfig } from '@frak-labs/core-sdk'; const config: FrakWalletSdkConfig = { metadata: { name: "My App", }, // When true (default): components show a loading spinner until backend config is resolved // When false: components render immediately with local config / HTML attributes waitForBackendConfig: true, }; ``` :::tip Keep `waitForBackendConfig: true` (the default) if you rely on backend-managed settings like translations, custom CSS, or placements. Set it to `false` if you provide all configuration locally and want instant rendering. ::: ## Caching The SDK caches the resolved configuration in `localStorage` with a 30-second TTL using a stale-while-revalidate strategy: - **Fresh cache** (< 30 seconds): The cached config is used immediately, no network request. - **Stale cache** (> 30 seconds): The cached config is used immediately for fast rendering, while a background fetch updates the cache. - **No cache**: A network request is made and components wait for the response (or render immediately if `waitForBackendConfig` is `false`). The cache is scoped per domain and language, so different subdomains or language settings maintain separate caches. ## Managing Backend Configuration Backend-driven configuration is managed from the **business dashboard**. Navigate to your merchant's settings to configure: - **Branding** — Name, logo, homepage link - **Display** — Language, currency, visibility toggle - **Styling** — Custom CSS for modals and components - **Translations** — Override default text for any SDK component - **Placements** — Create named configurations for different sections of your site (see [Placements](/developers/concepts/placements)) Changes made in the dashboard take effect on your website within 30 seconds (the cache TTL), without requiring any code changes or redeployment. # Wallet SDK Configuration > Learn how to configure the Wallet SDK for your application import { Tabs, TabItem } from "@astrojs/starlight/components"; # Configuration Proper configuration is crucial for the Wallet SDK to function correctly in your application. This guide will walk you through the configuration options and how to set them up. ## Configuration Object The Wallet SDK uses a configuration object to set up its behavior. Here's the structure of the `FrakWalletSdkConfig` object: ```ts twoslash // [!include ~/snippets/types/FrakWalletSdkConfig.ts] ``` ```js /** * @typedef {Object} FrakWalletSdkConfig * @property {string} [walletUrl] - The URL of the Frak Wallet service * @property {Object} metadata - Metadata about your application * @property {string} [metadata.name] - The name of your application * @property {string} [metadata.merchantId] - Your merchant ID (UUID) from the Frak dashboard * @property {string} [metadata.lang] - The default language ("en" | "fr") * @property {string} [metadata.currency] - The default currency ("eur" | "usd" | "gbp") * @property {string} [metadata.logoUrl] - Logo URL displayed in modals and components * @property {string} [metadata.homepageLink] - Link to your homepage * @property {Object} [customizations] - Customization options * @property {string} [customizations.css] - URL to a CSS file for styling * @property {Object} [customizations.i18n] - Translation overrides for SDK components * @property {string} [domain] - The domain of your application * @property {boolean} [waitForBackendConfig] - Wait for backend config before rendering (default: true) * @property {Object} [attribution] - Default attribution params (UTM / via / ref) appended to outbound sharing URLs * @property {string[]} [preload] - UI views to preload in the listener iframe ("modal" | "sharing", default: ["sharing"]) */ ``` Let's break down each property: ### `walletUrl` (optional) This is the URL of the Frak Wallet service. Use one of the following values: - Production: `"https://wallet.frak.id"` - Development: `"https://wallet-dev.frak.id"` :::tip This property is optional. If not provided, it defaults to the production URL (`"https://wallet.frak.id"`). ::: ### `metadata` This object contains metadata about your application: - `name` (optional): The name of your application. Displayed in modals and SSO pages. - `merchantId` (optional): Your merchant ID from the Frak dashboard (UUID format). Used for referral tracking and analytics. If not provided, it will be auto-fetched from the backend using your domain. - `lang` (optional): The display language (`"en"` or `"fr"`). Defaults to the browser language. - `currency` (optional): The display currency (`"eur"`, `"usd"`, or `"gbp"`). Defaults to `"eur"`. - `logoUrl` (optional): Logo URL displayed in modals and a few components. - `homepageLink` (optional): Link to your homepage, used in SSO pages and some components. ### `customizations` This object contains customization options for the displayed Frak elements: - `css` (optional): A URL to a CSS file (must end with `.css`) that styles the Frak Wallet interface when displayed in your application. - `i18n` (optional): An object containing text overrides for SDK components. Can be a single-language config or a multi-language config keyed by language code. :::caution URL-based i18n configuration has been removed. Only inline objects are supported. ::: ### `domain` (optional) The domain of your application. This is used to identify your application in the Frak ecosystem. :::tip This property is optional. If not provided, it will be automatically retrieved during initialization. ::: ### `waitForBackendConfig` (optional) Controls whether components wait for the [backend-driven configuration](/developers/concepts/backend-configuration) to be resolved before rendering. - `true` (default): Components show a loading spinner until backend config is resolved. - `false`: Components render immediately with local config and HTML attributes. ### `attribution` (optional) Default attribution parameters (`utmSource`, `utmMedium`, `utmCampaign`, `utmTerm`, `via`, `ref`) appended to outbound sharing URLs. Per-call `displaySharingPage` overrides take precedence, then backend config, then this SDK-level default. `utmContent` is intentionally excluded, as it is per-content rather than a merchant-wide default. ### `preload` (optional) UI views to preload inside the listener iframe for a snappier first display. Accepts an array of `"modal"` and/or `"sharing"`. :::tip Defaults to `["sharing"]`. ::: ## Example Configuration Here's an example of a complete configuration object: ```ts twoslash // @noErrors import type { FrakWalletSdkConfig } from '@frak-labs/core-sdk'; const frakConfig: FrakWalletSdkConfig = { walletUrl: "https://wallet.frak.id", metadata: { name: "My Awesome dApp", lang: "en", currency: "usd", logoUrl: "https://my-app.com/logo.png", homepageLink: "https://my-app.com", }, customizations: { css: "https://my-app.com/frak-styles.css", i18n: { en: { "sdk.modal.title": "Welcome!", }, fr: { "sdk.modal.title": "Bienvenue !", "sharing.title": "Partage ce produit!", } } }, domain: "my-app.com", }; ``` ## Using the Configuration How you use this configuration depends on whether you're using React or vanilla JavaScript: ### React In a React application, use the `FrakConfigProvider` to provide this configuration to your app: ```tsx twoslash // @noErrors import { FrakConfigProvider, FrakIFrameClientProvider } from '@frak-labs/react-sdk'; const frakConfig = { metadata: { name: "My Awesome dApp", }, }; function App() { return ( {/* Your app components */} ); } ``` ### Vanilla JavaScript In a vanilla JavaScript application, pass this configuration when creating a Frak client: ```ts twoslash // @noErrors import { createIFrameFrakClient, createIframe } from '@frak-labs/core-sdk'; const frakConfig = { metadata: { name: "My Awesome dApp", }, }; const iframe = createIframe({ config: frakConfig }); const client = await createIFrameFrakClient({ config: frakConfig, iframe }); ``` ## Best Practices 1. **Environment-based Configuration**: Consider using different configurations for development and production environments. This allows you to use the development Frak Wallet during testing. 2. **Secure CSS**: If you're providing a custom CSS file, ensure it's served over HTTPS to prevent security issues. 3. **Domain Consistency**: If you provide a `domain`, make sure it matches the actual domain where your application is hosted. Mismatches can lead to authentication issues. 4. **Iframe Creation**: Always use the `createIframe` helper function provided by the SDK to create the iframe. This ensures proper setup and compatibility. :::caution Remember to handle any potential errors when creating the iframe or initializing the client. ::: By properly configuring the Wallet SDK, you ensure that it can communicate effectively with the Frak Wallet and provide a seamless experience for your users. ## Next Steps - [Backend-Driven Configuration](/developers/concepts/backend-configuration) — Learn how the SDK dynamically resolves settings from the Frak backend. - [Placements](/developers/concepts/placements) — Customize component behavior for different sections of your website. - [Tracking User Interactions](/developers/concepts/interactions) — Learn about interaction tracking. # Understanding Interactions > Learn how to leverage interactions in the Wallet SDK for tracking user engagement, implementing reward systems, and enhancing your application's functionality. # Interactions Interactions are the cornerstone of user engagement tracking in the Wallet SDK. They allow developers to record events based on user actions within their applications, enabling features like reward systems and engagement analytics. ## How Interactions Work 1. **Automatic Tracking**: The SDK tracks user arrivals, referrals, and sharing events through a simple fire-and-forget API. 2. **Merchant Resolution**: The SDK automatically resolves your merchant identity from your domain — no need to pass product or merchant IDs manually. 3. **Offline Support**: If a user isn't logged in, interactions are stored locally in the browser and sent once a session is established, ensuring privacy and data integrity. 4. **Transparent Process**: The entire interaction recording process is seamless and invisible to the user. ## Interaction Types The SDK supports three interaction types: - **`arrival`** — Track when a user lands on your site, with optional referral attribution. - **`sharing`** — Track when a user shares your content via the sharing modal. - **`custom`** — Track any custom event specific to your application. ## Sending Interactions Use the [`sendInteraction`](/developers/references/core-sdk/actions/functions/sendinteraction/) action to record events: ```ts twoslash // @noErrors import { sendInteraction } from '@frak-labs/core-sdk/actions'; // Track a user arrival with referral attribution await sendInteraction(client, { type: "arrival", referrerWallet: "0x1234...abcd", }); // Track a sharing event await sendInteraction(client, { type: "sharing" }); // Send a custom interaction await sendInteraction(client, { type: "custom", customType: "newsletter_signup", data: { email: "user@example.com" }, }); ``` `sendInteraction` is fire-and-forget: errors are caught and logged, not thrown. ## Referral Interactions For referral tracking, the SDK provides a dedicated helper that handles the full referral flow automatically: ```ts twoslash // @noErrors import { referralInteraction } from '@frak-labs/core-sdk/actions'; const result = await referralInteraction(client, { options: { alwaysAppendUrl: true, merchantId: "550e8400-e29b-41d4-a716-446655440000", }, }); ``` See [`referralInteraction`](/developers/references/core-sdk/actions/functions/referralinteraction/) for details. ## Benefits of Interactions - **Engagement Tracking**: Monitor user activity on your platform. - **Reward Systems**: Implement campaigns that distribute rewards based on user interactions. - **Privacy-Preserving**: Interactions are only sent when a user has an active session. - **Flexible Integration**: Use built-in types or define custom interactions for your specific use case. ## Best Practices - Use the `referralInteraction` helper for referral flows instead of manually composing arrival interactions. - Set default UTM / attribution params via the SDK [`attribution` config](/developers/concepts/configuration/#attribution-optional) to improve marketing attribution on shared links. - Use `idempotencyKey` on custom interactions to prevent duplicate event recording. For detailed parameter information, refer to the [`SendInteractionParamsType`](/developers/references/core-sdk/index/type-aliases/sendinteractionparamstype/) reference. # Placements > Use placements to customize SDK components for different sections of your website # Placements Placements let you define named configurations that customize how SDK components behave on different sections of your website. Instead of using the same global settings everywhere, you can create placements like `"homepage"`, `"product-page"`, or `"checkout"` — each with its own text, styling, and behavior. ## How Placements Work 1. **Create placements** in the [business dashboard](/guides/dashboard) under your merchant's customization settings. 2. **Assign a placement** to any SDK component using the `placement` attribute or prop. 3. **The component resolves** its configuration from the [backend-driven config](/developers/concepts/backend-configuration), applying placement-specific overrides on top of global defaults. ``` Global Config (dashboard defaults) └── Placement: "homepage" │ └── buttonShare: { text: "Share this!", clickAction: "sharing-page" } │ └── banner: { referralTitle: "Join our community" } └── Placement: "checkout" └── postPurchase: { ctaText: "Share and earn {REWARD}!" } └── buttonShare: { text: "Tell your friends" } ``` ## Using Placements with Web Components All Frak web components accept a `placement` attribute. When provided, the component looks up its configuration from the matching placement in the backend config. ### Share Button ```html ``` ### Post-Purchase ```html ``` ### Banner ```html ``` ### Wallet Button ```html ``` ### Open in App ```html ``` ## Using Placements with the Core SDK When calling SDK actions directly (without web components), pass the placement ID as the third argument: ```ts twoslash // @noErrors import { displayModal, displayEmbeddedWallet } from '@frak-labs/core-sdk/actions'; // Display a modal associated with the "checkout" placement const results = await displayModal(client, { steps: { login: { allowSso: true }, final: { action: { key: "sharing" } }, }, }, "checkout"); // Display the embedded wallet for the "homepage" placement await displayEmbeddedWallet(client, { loggedIn: { action: { key: "sharing" } }, }, "homepage"); ``` ## Placement Configuration Options Each placement can customize the following components. Settings defined at the placement level override the global component defaults. ### Share Button (`buttonShare`) | Option | Type | Description | |--------|------|-------------| | `text` | `string` | Button text. Use `{REWARD}` placeholder for reward amount. | | `noRewardText` | `string` | Fallback text when no reward is available. | | `clickAction` | `"embedded-wallet"` \| `"share-modal"` \| `"sharing-page"` | Which UI opens on click. | | `useReward` | `boolean` | Whether to display the reward amount. | | `css` | `string` | Component-specific CSS override. | ### Wallet Button (`buttonWallet`) | Option | Type | Description | |--------|------|-------------| | `position` | `"right"` \| `"left"` | Screen position of the floating wallet button. | | `css` | `string` | Component-specific CSS override. | ### Post-Purchase (`postPurchase`) | Option | Type | Description | |--------|------|-------------| | `badgeText` | `string` | Text for the badge pill above the message. | | `refereeText` | `string` | Message shown to referred users. Use `{REWARD}` placeholder. | | `refereeNoRewardText` | `string` | Fallback message for referees when no reward is found. | | `referrerText` | `string` | Message shown to referrers. Use `{REWARD}` placeholder. | | `referrerNoRewardText` | `string` | Fallback message for referrers when no reward is found. | | `ctaText` | `string` | CTA button text. Use `{REWARD}` placeholder. | | `ctaNoRewardText` | `string` | Fallback CTA text when no reward is found. | | `css` | `string` | Component-specific CSS override. | ### Banner (`banner`) | Option | Type | Description | |--------|------|-------------| | `referralTitle` | `string` | Title for the referral banner variant. | | `referralDescription` | `string` | Description for the referral banner. | | `referralCta` | `string` | CTA button text for the referral banner. | | `inappTitle` | `string` | Title for the in-app browser banner variant. | | `inappDescription` | `string` | Description for the in-app browser banner. | | `inappCta` | `string` | CTA button text for the in-app browser banner. | | `css` | `string` | Component-specific CSS override. | ### Open in App (`openInApp`) | Option | Type | Description | |--------|------|-------------| | `text` | `string` | Button text override. | | `css` | `string` | Component-specific CSS override. | ### Placement-Level Settings In addition to component-specific settings, each placement also supports: | Option | Type | Description | |--------|------|-------------| | `targetInteraction` | `string` | The interaction type to use for reward calculations in this placement. | | `translations` | `Record` | Placement-specific translation overrides. | | `css` | `string` | Global CSS applied to modals displayed from this placement. | ## Placement vs. HTML Attributes Component settings can come from two sources: **placement configuration** (backend-driven) and **HTML attributes** (inline). When both are present, HTML attributes take precedence, allowing you to override placement defaults for specific instances. ```html ``` ## Example: Multi-Page Setup Here's an example of using different placements across a website: ```html ``` Each placement is configured independently in the business dashboard, giving you full control over text, styling, and behavior per section — without changing your code. ## Next Steps - [Backend-Driven Configuration](/developers/concepts/backend-configuration) — Learn how the SDK resolves configuration from the backend. - [Configuration](/developers/concepts/configuration) — Set up local SDK configuration. - [Components](/developers/components) — Explore all available web components. # CDN / Browser Integration > Learn how to integrate the Wallet SDK into your Vanilla JavaScript application for seamless Web3 interactions. # Vanilla JS Integration Guide This guide will walk you through the process of integrating the Wallet SDK into your Vanilla JavaScript application. By the end, you'll have a basic setup that allows users to connect their Frak Wallet and perform simple interactions. ## Prerequisites Before you begin, ensure that: 1. You have a basic HTML/JavaScript project set up. 2. You have a merchant account on the [Frak business dashboard](https://business.frak.id/) with your storefront's domain registered. The main domain is registered automatically at sign-up; for subdomains, add them under **Allowed Domains** on the dashboard. If you haven't completed these steps, please refer to the [Getting Started](/guides) guide. ## Step 1: Install Dependencies For a Vanilla JS project, you can include the Wallet SDK via a CDN. Add the following script tag to your HTML file: ```html title="CDN Bundle" ``` ## Step 2: Set Up the Frak Client Create a new JavaScript file (e.g., `frak-setup.js`) to set up the Frak client: ```javascript // frak-setup.js const frakConfig = { metadata: { name: 'Your App Name', }, }; async function setupFrakClient() { const client = await FrakSDK.setupClient({ config: frakConfig }); if (!client) { console.error('Failed to create Frak client'); return null; } return client; } // Export the setup function and config for use in other files window.FrakSetup = { setupFrakClient, frakConfig }; ``` For more detailed configuration options, see [FrakWalletSdkConfig](/developers/references/core-sdk/index/type-aliases/frakwalletsdkconfig/). Include this script in your HTML file: ```html ``` ## Step 3: Check Wallet Status Create a function to check and display the wallet status, using the [`watchWalletStatus`](/developers/references/core-sdk/actions/functions/watchwalletstatus/) action: ```javascript // wallet-status.js async function displayWalletStatus() { const client = await window.FrakSetup.setupFrakClient(); if (!client) { console.error('Frak client not initialized'); return; } const statusElement = document.getElementById('wallet-status'); statusElement.textContent = 'Checking wallet status...'; try { await FrakSDK.watchWalletStatus(client, (status) => { statusElement.textContent = `Wallet status: ${status.key === 'connected' ? 'Connected' : 'Not connected'}`; }); } catch (error) { statusElement.textContent = `Error: ${error.message}`; } } // Call this function when the page loads window.addEventListener('load', displayWalletStatus); ``` ## Step 4: Implement Login Modal Create a function to handle the login process, using the [`displayModal`](/developers/references/core-sdk/actions/functions/displaymodal/) action: ```javascript // login-button.js async function handleLogin() { const client = await window.FrakSetup.setupFrakClient(); if (!client) { console.error('Frak client not initialized'); return; } const loginButton = document.getElementById('login-button'); loginButton.disabled = true; loginButton.textContent = 'Logging in...'; try { await FrakSDK.displayModal(client, { steps: { login: {}, final: { action: { key: "sharing" }, } } }); loginButton.textContent = 'Logged In'; } catch (error) { console.error('Login error:', error); loginButton.textContent = 'Login Failed'; } finally { loginButton.disabled = false; } } // Attach the login handler to the button window.addEventListener('load', () => { const loginButton = document.getElementById('login-button'); loginButton.addEventListener('click', handleLogin); }); ``` ## Step 5: Put It All Together Update your HTML file to include all the necessary elements and scripts: ```html My Frak-Enabled App

My Frak-Enabled App

Initializing...
``` ## Next Steps With this setup, you have a basic Vanilla JavaScript application integrated with the Wallet SDK. Users can now connect their Frak Wallet and log in. From here, you can start implementing more advanced features such as: - Sending interactions - Implementing referral systems - Creating reward campaigns Refer to the specific action documentation for details on implementing these features in a Vanilla JS environment. # Installation via Package Manager > Learn how to integrate the Wallet SDK into your JavaScript / Typescript application for seamless Web3 interactions. import { Tabs, TabItem } from "@astrojs/starlight/components"; # Installation via Package Manager This guide will walk you through the process of integrating the Wallet SDK into your JavaScript / Typescript application. By the end, you'll have a basic setup that allows users to connect their Frak Wallet and perform interactions. ## Prerequisites Before you begin, ensure that: 1. You have a package manager set up on your project (npm / bun / pnpm or yarn). 2. You have a merchant account on the [Frak business dashboard](https://business.frak.id/) with your storefront's domain registered. The main domain is registered automatically at sign-up; for subdomains, add them under **Allowed Domains** on the dashboard. If you haven't completed these steps, please refer to the [Getting Started](/guides) guide. ## Step 1: Install Dependencies ```bash npm install @frak-labs/core-sdk ``` ```bash yarn install @frak-labs/core-sdk ``` ```bash pnpm install @frak-labs/core-sdk ``` ```bash bun install @frak-labs/core-sdk ``` ## Step 2: Set Up the Frak Client Create a new TypeScript file (e.g., `frak-setup.ts`) to set up the Frak client: ```typescript import { setupClient, type FrakWalletSdkConfig } from '@frak-labs/core-sdk'; const frakConfig: FrakWalletSdkConfig = { metadata: { name: 'Your App Name', }, }; export async function setupFrakClient() { const client = await setupClient({ config: frakConfig }); if (!client) { console.error('Failed to create Frak client'); return null; } return client; } export { frakConfig }; ``` For more detailed configuration options, see [FrakWalletSdkConfig](/developers/references/core-sdk/index/type-aliases/frakwalletsdkconfig/). ## Step 3: Check Wallet Status Create a function to check and display the wallet status, using the [`watchWalletStatus`](/developers/references/core-sdk/actions/functions/watchwalletstatus/) action: ```typescript import { watchWalletStatus } from '@frak-labs/core-sdk/actions'; import { setupFrakClient } from './frak-setup'; export async function displayWalletStatus() { const client = await setupFrakClient(); if (!client) { console.error('Frak client not initialized'); return; } const statusElement = document.getElementById('wallet-status'); if (!statusElement) return; statusElement.textContent = 'Checking wallet status...'; try { await watchWalletStatus(client, (status) => { if (!statusElement) return; statusElement.textContent = `Wallet status: ${status.key === 'connected' ? 'Connected' : 'Not connected'}`; }); } catch (error) { statusElement.textContent = `Error: ${error instanceof Error ? error.message : 'Unknown error'}`; } } // Call this function when the page loads window.addEventListener('load', displayWalletStatus); ``` ## Step 4: Implement Login Modal Create a function to handle the login process, using the [`displayModal`](/developers/references/core-sdk/actions/functions/displaymodal/) action: ```typescript import { displayModal } from '@frak-labs/core-sdk/actions'; import { setupFrakClient } from './frak-setup'; export async function handleLogin() { const client = await setupFrakClient(); if (!client) { console.error('Frak client not initialized'); return; } const loginButton = document.getElementById('login-button') as HTMLButtonElement | null; if (!loginButton) return; loginButton.disabled = true; loginButton.textContent = 'Logging in...'; try { await displayModal(client, { steps: { login: {}, final: { action: { key: "sharing" }, } } }); loginButton.textContent = 'Logged In'; } catch (error) { console.error('Login error:', error); loginButton.textContent = 'Login Failed'; } finally { loginButton.disabled = false; } } // Attach the login handler to the button window.addEventListener('load', () => { const loginButton = document.getElementById('login-button'); loginButton?.addEventListener('click', handleLogin); }); ``` ## Step 5: Put It All Together Create an HTML file that includes your bundled JavaScript: ```html My Frak-Enabled App

My Frak-Enabled App

Initializing...
``` Note: Make sure your bundler (webpack, vite, etc.) is properly configured to handle TypeScript files and generate the bundle.js file. ## Next Steps With this setup, you have a basic TypeScript application integrated with the Wallet SDK. Users can now connect their Frak Wallet and log in. From here, you can start implementing more advanced features such as: - Sending interactions - Implementing referral systems - Creating reward campaigns Refer to the specific action documentation for details on implementing these features using the SDK's TypeScript interfaces and types. # React Start Guide > Learn how to integrate the Wallet SDK into your React application for seamless Web3 interactions. import { Tabs, TabItem } from "@astrojs/starlight/components"; # React Integration Guide This guide will walk you through the process of integrating the Wallet SDK into your React application. By the end, you'll have a basic setup that allows users to connect their Frak Wallet and perform simple interactions. ## Prerequisites Before you begin, ensure that: 1. You have a React project set up. 2. You have a merchant account on the [Frak business dashboard](https://business.frak.id/) with your storefront's domain registered. The main domain is registered automatically at sign-up; for subdomains, add them under **Allowed Domains** on the dashboard. If you haven't completed these steps, please refer to the [Getting Started](/guides) guide. ## Step 1: Install Dependencies First, install the required packages: ```bash npm install @frak-labs/react-sdk @tanstack/react-query ``` ```bash yarn add @frak-labs/react-sdk @tanstack/react-query ``` ```bash pnpm add @frak-labs/react-sdk @tanstack/react-query ``` ```bash bun add @frak-labs/react-sdk @tanstack/react-query ``` ## Step 2: Set Up the Frak Client Create a new component to set up the Frak client and iframe: ```tsx twoslash title="FrakProvider.tsx" // @noErrors // [!include ~/snippets/integration/FrakProvider.tsx] ``` Wrap your main App component with this provider: ```tsx twoslash title="App.tsx" // @noErrors import { FrakProvider } from './FrakProvider'; function App() { return ( {/* Your app content */} ); } export default App; ``` For more detailed configuration options, see [FrakWalletSdkConfig](/developers/references/core-sdk/index/type-aliases/frakwalletsdkconfig/). ## Step 3: Check Wallet Status Create a component to check and display the wallet status using the [useWalletStatus](/developers/references/react-sdk/functions/usewalletstatus/) hook: ```tsx twoslash title="WalletStatus.tsx" // @noErrors // [!include ~/snippets/integration/react-app.tsx:wallet-status] ``` ## Step 4: Implement Login Modal Create a component for the login modal, using the [useDisplayModal](/developers/references/react-sdk/functions/usedisplaymodal/) hook: ```tsx twoslash title="LoginButton.tsx" // @noErrors // [!include ~/snippets/integration/react-app.tsx:login-button] ``` ## Step 5: Put It All Together Update your main App component to include the wallet status and login button: ```tsx twoslash // @noErrors // [!include ~/snippets/integration/react-app.tsx:app] ``` ```tsx twoslash // @noErrors // [!include ~/snippets/integration/react-app.tsx] ``` ```tsx twoslash // @noErrors // [!include ~/snippets/integration/FrakProvider.tsx] ``` ## Next Steps With this setup, you have a basic React application integrated with the Wallet SDK. Users can now connect their Frak Wallet and log in. From here, you can start implementing more advanced features such as: - Sending interactions - Implementing referral systems - Creating reward campaigns Refer to the specific action and hook documentation for details on implementing these features. # Banner > **Banner**(`__namedParameters`): `Element` \| `null` Defined in: [vendor/wallet/sdk/components/src/components/Banner/Banner.tsx:75](https://github.com/frak-id/wallet/blob/da58e5f874a69966502537d9611590646b89891e/sdk/components/src/components/Banner/Banner.tsx#L75) Auto-detecting notification banner component. Renders an inline banner on the merchant page with one of two distinct visual styles depending on the detected mode: - **Referral mode** (white): Shown after a successful referral link processing. Displays a gift icon, reward copy, and a "Got it" CTA. - **In-app browser mode** (dark transparent): Shown when the page is opened inside a social media in-app browser (Instagram, Facebook). Offers an inline link to redirect to the default browser plus a close button to dismiss. In-app browser mode takes priority over referral mode. Uses Light DOM + vanilla-extract styles from `@frak-labs/design-system`. ## Parameters ### \_\_namedParameters #### allowInappRedirect? `boolean` \| `"true"` \| `"false"` When `true` (default `false`), the banner is allowed to switch to in-app browser mode (Instagram / Facebook WebView) and prompt the user to escape to the system browser. Most flows now work inside in-app browsers via the anonymous-id flow, so the redirect is opt-in. Enable it only on surfaces that actually drive users into a WebAuthn-bound action (login, sendTransaction, SIWE authenticate). Accepts the boolean `true` (TS/JSX) or the string `"true"` (HTML attribute). Any other value — including `false`, `"false"`, the empty string, or attribute absence — keeps the redirect disabled. #### classname? `string` = `""` CSS class names passed through to the root element (Light DOM). #### imageUrl? `string` Override the image displayed on the left of the referral banner. Accepts an image URL. Falls back to the built-in gift icon when omitted. The image is constrained to the icon slot via `object-fit: contain`, so any aspect ratio renders correctly. #### inappCta? `string` Override the in-app browser banner CTA button text. #### inappDescription? `string` Override the in-app browser banner description. #### inappTitle? `string` Override the in-app browser banner title. #### interaction? `"referral"` \| `"create_referral_link"` \| `"purchase"` \| `` `custom.${string}` `` Filter rewards by interaction type (e.g. "purchase", "referral"). When omitted, the best reward across all interaction types is shown. #### placement? `string` Placement ID for backend-driven CSS customization. #### preview? `string` When set, forces the banner to render in preview mode (e.g. in Shopify theme editor). Bypasses normal event/browser detection and shows static content. #### previewMode? `"referral"` \| `"inapp"` Which banner variant to preview: "referral" or "inapp". Only used when preview is set. Defaults to "referral". #### referralCta? `string` Override the referral banner CTA button text. #### referralDescription? `string` Override the referral banner description. #### referralTitle? `string` Override the referral banner title. ## Returns `Element` \| `null` ## Examples Basic usage (auto-detects mode): ```html ``` With a custom class: ```html ``` # ButtonShare > **ButtonShare**(`args`): `Element` \| `null` Defined in: [vendor/wallet/sdk/components/src/components/ButtonShare/ButtonShare.tsx:59](https://github.com/frak-id/wallet/blob/da58e5f874a69966502537d9611590646b89891e/sdk/components/src/components/ButtonShare/ButtonShare.tsx#L59) Button to share the current page ## Parameters ### args #### classname? `string` = `""` Classname to apply to the button #### clickAction? `"embedded-wallet"` \| `"sharing-page"` Which UI to open on click. Legacy values (e.g. `"share-modal"`) are accepted at runtime and gracefully route to the full-page sharing UI — the modal-flow share path was retired in favour of `displaySharingPage`. **Default Value** `"sharing-page"` #### noRewardText? `string` Fallback text when `text` contains the `{REWARD}` placeholder but no reward is available. #### placement? `string` #### preview? `string` When set, renders the button in preview mode (e.g. Shopify/WP editor). Skips the client-ready gating so the button is always enabled visually, and no-ops the click handler so merchants can see the final layout with their configured copy even when no Frak client is initialized. #### targetInteraction? `"referral"` \| `"create_referral_link"` \| `"purchase"` \| `` `custom.${string}` `` Target interaction behind this sharing action (will be used to get the right reward to display) #### text? `string` Text to display on the button. Including the placeholder `{REWARD}` (e.g. `Share and earn up to \{REWARD\}!`) opts the button into the live reward flow: the SDK fetches the estimated reward and substitutes the placeholder. When no reward is available, `noRewardText` is used as a fallback (or the placeholder is stripped if no fallback is provided). When omitted, a built-in localized default is used based on the resolved language (`"Share and earn!"` / `"Partagez et gagnez !"`). ## Returns `Element` \| `null` The share button with `; } ``` ## See - [\`prepareSso()\`](/developers/references/core-sdk/actions/functions/preparesso/) for the underlying action - [\`openSso()\`](/developers/references/core-sdk/actions/functions/opensso/) for the recommended high-level API # useReferralInteraction > **useReferralInteraction**(`args?`): `Error` \| `"idle"` \| `"processing"` \| `"success"` \| `"no-referrer"` \| `"self-referral"` Defined in: [react/src/hook/helper/useReferralInteraction.ts:26](https://github.com/frak-id/wallet/blob/da58e5f874a69966502537d9611590646b89891e/sdk/react/src/hook/helper/useReferralInteraction.ts#L26) Helper hook to automatically submit a referral interaction when detected Runs once when the Frak client becomes available. ## Parameters ### args? #### options? `ProcessReferralOptions` Some options for the referral interaction ## Returns `Error` \| `"idle"` \| `"processing"` \| `"success"` \| `"no-referrer"` \| `"self-referral"` The resulting referral state, or a potential error ## Description This function will automatically handle the referral interaction process ## See [\`referralInteraction()\`](/developers/references/core-sdk/actions/functions/referralinteraction/) for more details on the automatic referral handling process # useSendTransactionAction > **useSendTransactionAction**(`args?`): `UseMutationResult`\<\{ `hash`: `` `0x${string}` ``; \}, `FrakRpcError`\<`undefined`\>, \{ `metadata?`: `ModalRpcMetadata`; `tx`: `SendTransactionTxType` \| `SendTransactionTxType`[]; \}, `unknown`\> Defined in: [react/src/hook/useSendTransaction.ts:45](https://github.com/frak-id/wallet/blob/da58e5f874a69966502537d9611590646b89891e/sdk/react/src/hook/useSendTransaction.ts#L45) Hook that return a mutation helping to send a transaction It's a @tanstack/react-query!home \| \`tanstack\` wrapper around the [\`sendTransaction()\`](/developers/references/core-sdk/actions/functions/sendtransaction/) action ## Parameters ### args? Optional config object with `mutations` for customizing the underlying @tanstack/react-query!useMutation \| \`useMutation()\` #### mutations? `MutationOptions` Optional mutation options, see @tanstack/react-query!useMutation \| \`useMutation()\` for more infos ## Returns `UseMutationResult`\<\{ `hash`: `` `0x${string}` ``; \}, `FrakRpcError`\<`undefined`\>, \{ `metadata?`: `ModalRpcMetadata`; `tx`: `SendTransactionTxType` \| `SendTransactionTxType`[]; \}, `unknown`\> The mutation hook wrapping the `sendTransaction()` action The `mutate` and `mutateAsync` argument is of type [\`SendTransactionParams\`](/developers/references/core-sdk/actions/type-aliases/sendtransactionparams/) The `data` result is a [\`SendTransactionReturnType\`](/developers/references/core-sdk/index/type-aliases/sendtransactionreturntype/) ## See - [\`sendTransaction()\`](/developers/references/core-sdk/actions/functions/sendtransaction/) for more info about the underlying action - @tanstack/react-query!useMutation \| \`useMutation()\` for more info about the mutation options and response # useSetupReferral > **useSetupReferral**(): `UseQueryResult`\<`null`, `Error`\> Defined in: [react/src/hook/useSetupReferral.ts:20](https://github.com/frak-id/wallet/blob/da58e5f874a69966502537d9611590646b89891e/sdk/react/src/hook/useSetupReferral.ts#L20) Hook that automatically processes referral context and emits a DOM event on success Runs once when the Frak client becomes available. Fire-and-forget — the referral result is tracked via a `"frak:referral-success"` DOM event on `window`, not via the returned query data. ## Returns `UseQueryResult`\<`null`, `Error`\> The query handle (data is not meaningful — listen for `REFERRAL_SUCCESS_EVENT` on `window` instead) ## See - [\`setupReferral()\`](/developers/references/core-sdk/actions/functions/setupreferral/) for more info about the underlying action - [\`REFERRAL\_SUCCESS\_EVENT\`](/developers/references/core-sdk/actions/variables/referral_success_event/) for the event name constant # useSiweAuthenticate > **useSiweAuthenticate**(`args?`): `UseMutationResult`\<\{ `message`: `string`; `signature`: `` `0x${string}` ``; \}, `FrakRpcError`\<`undefined`\>, \{ `metadata?`: `ModalRpcMetadata`; `siwe?`: `Partial`\<`SiweAuthenticationParams`\>; \}, `unknown`\> Defined in: [react/src/hook/useSiweAuthenticate.ts:45](https://github.com/frak-id/wallet/blob/da58e5f874a69966502537d9611590646b89891e/sdk/react/src/hook/useSiweAuthenticate.ts#L45) Hook that return a mutation helping to send perform a SIWE authentication It's a @tanstack/react-query!home \| \`tanstack\` wrapper around the [\`siweAuthenticate()\`](/developers/references/core-sdk/actions/functions/siweauthenticate/) action ## Parameters ### args? `UseSiweAuthenticateParams` = `{}` Optional config object with `mutations` for customizing the underlying @tanstack/react-query!useMutation \| \`useMutation()\` ## Returns `UseMutationResult`\<\{ `message`: `string`; `signature`: `` `0x${string}` ``; \}, `FrakRpcError`\<`undefined`\>, \{ `metadata?`: `ModalRpcMetadata`; `siwe?`: `Partial`\<`SiweAuthenticationParams`\>; \}, `unknown`\> The mutation hook wrapping the `siweAuthenticate()` action The `mutate` and `mutateAsync` argument is of type [\`SiweAuthenticateModalParams\`](/developers/references/core-sdk/actions/type-aliases/siweauthenticatemodalparams/) The `data` result is a [\`SiweAuthenticateReturnType\`](/developers/references/core-sdk/index/type-aliases/siweauthenticatereturntype/) ## See - [\`siweAuthenticate()\`](/developers/references/core-sdk/actions/functions/siweauthenticate/) for more info about the underlying action - @tanstack/react-query!useMutation \| \`useMutation()\` for more info about the mutation options and response # useWalletStatus > **useWalletStatus**(): `UseQueryResult`\<`WalletStatusReturnType`, `Error`\> Defined in: [react/src/hook/useWalletStatus.ts:22](https://github.com/frak-id/wallet/blob/da58e5f874a69966502537d9611590646b89891e/sdk/react/src/hook/useWalletStatus.ts#L22) Hook that return a query helping to get the current wallet status. It's a @tanstack/react-query!home \| \`tanstack\` wrapper around the [\`watchWalletStatus()\`](/developers/references/core-sdk/actions/functions/watchwalletstatus/) action ## Returns `UseQueryResult`\<`WalletStatusReturnType`, `Error`\> The query hook wrapping the `watchWalletStatus()` action The `data` result is a [\`WalletStatusReturnType\`](/developers/references/core-sdk/index/type-aliases/walletstatusreturntype/) ## See - [\`watchWalletStatus()\`](/developers/references/core-sdk/actions/functions/watchwalletstatus/) for more info about the underlying action - @tanstack/react-query!useQuery \| \`useQuery()\` for more info about the useQuery response # FrakConfigProviderProps > **FrakConfigProviderProps** = \{ `config`: `FrakWalletSdkConfig`; \} Defined in: [react/src/provider/FrakConfigProvider.ts:17](https://github.com/frak-id/wallet/blob/da58e5f874a69966502537d9611590646b89891e/sdk/react/src/provider/FrakConfigProvider.ts#L17) Props to instantiate the Frak Wallet SDK configuration provider ## Properties ### config > **config**: `FrakWalletSdkConfig` Defined in: [react/src/provider/FrakConfigProvider.ts:22](https://github.com/frak-id/wallet/blob/da58e5f874a69966502537d9611590646b89891e/sdk/react/src/provider/FrakConfigProvider.ts#L22) The wanted Frak configuration #### See [FrakWalletSdkConfig](/developers/references/core-sdk/index/type-aliases/frakwalletsdkconfig/) # FrakIFrameClientProps > **FrakIFrameClientProps** = \{ `config`: `FrakWalletSdkConfig`; \} Defined in: [react/src/provider/FrakIFrameClientProvider.ts:30](https://github.com/frak-id/wallet/blob/da58e5f874a69966502537d9611590646b89891e/sdk/react/src/provider/FrakIFrameClientProvider.ts#L30) Props to instantiate the Frak Wallet SDK configuration provider ## Properties ### config > **config**: `FrakWalletSdkConfig` Defined in: [react/src/provider/FrakIFrameClientProvider.ts:31](https://github.com/frak-id/wallet/blob/da58e5f874a69966502537d9611590646b89891e/sdk/react/src/provider/FrakIFrameClientProvider.ts#L31) # Documentation ## Packages - @frak-labs/components - @frak-labs/core-sdk - @frak-labs/react-sdk # How does it work? > How the frak wallet work under the hood? # How does it work? In this section, we will go through the different technologies and smart contracts used by the Frak Wallet, and how they are working together. ## Knowledge base Before deep diving into the Frak Wallet, it is important to understand a few blockchain technologies. ### Account Abstraction The frak wallet is using the [ERC-4337](https://eips.ethereum.org/EIPS/eip-4337) standard, which is a standard for account abstraction on EVM blockchain. If you are not familiar with this standard, here is a few great resources to get started: - [Awesome account abstraction](https://github.com/4337Mafia/awesome-account-abstraction) - [Stackup intro to account abstraction](https://docs.stackup.sh/docs/account-abstraction) - The EIP itself: [EIP-4337](https://eips.ethereum.org/EIPS/eip-4337) A few key takeaways from the account abstraction standard: - It permit to execute transaction without having to pay for the gas fees directly - It can be used with any type of validation (password, biometric, etc.) ### WebAuthN Then, the Frak wallet is using the [WebAuthN](https://w3c.github.io/webauthn/) standard for the authentication and the signing of the transactions. If you are not familiar with this standard, here is a few great resources to get started: - [Awesome WebAuthN](https://github.com/herrjemand/awesome-webauthn) - [Detailed WebAuthN demo by Auth0](https://webauthn.me/) - [WebAuthN demo by Matthew Miller](https://webauthn.io/) - [WebAuthN official documentation](https://w3c.github.io/webauthn/) - [WebAuthN on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API) A few key takeaways from the WebAuthN standard: - It's a standard for **passwordless** authentication - It's a standard for **secure message signing** - The authentication is bounded to a **specific domain**. ### P-256 Signature WebAuthN rely on the [secp256r1](https://neuromancer.sk/std/secg/secp256r1) signature algorithm (or in short *P-256*) to sign the transaction. This signature curve isn't supported on EVM chains by default. The [RIP-7212](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md) provides native support of this curve on rollup chains and is now live on several L2s including Base, Optimism, Arbitrum, and others. For chains that don't yet support this precompile, we fall back to the [FreshCryptoLib](https://github.com/rdubois-crypto/FreshCryptoLib) to verify the signature in Solidity. ## SmartWallet side In this section we will go through the smart contract related to the Smart wallet side of the Frak Wallet. We are using the [Kernel Smart Wallet](https://github.com/zerodevapp/kernel) by the [ZeroDev](https://zerodev.app/) team for core logic of the Smart Wallet. It's audited, battle tested, and has a lot of features that we can leverage (for example the [ERC-7579](https://erc7579.com/) support) Since kernel wallet support modular validation, we are mainly using two type of validator for the Frak Wallet: 1. The main one being the [FCL WebAuthN validator](https://github.com/zerodevapp/kernel/blob/dev/src/validator/webauthn/WebAuthnFclValidator.sol), a custom validator developed by us, using the [FreshCryptoLib](https://github.com/rdubois-crypto/FreshCryptoLib) to verify P-256 signatures on chains that don't yet support the RIP-7212 precompile (and using the native precompile where available). 2. The second one being the [ECDSAValidator](https://github.com/zerodevapp/kernel/blob/dev/src/validator/ECDSAValidator.sol), for users that set up recovery options. They can set up an EOA as a recovery wallet, enabling an ECDSAValidator. This permits them to execute transactions via either the WebAuthN validator or the ECDSA one. On the infrastructure side, we are using the [Pimlico bundler](https://www.pimlico.io/) to manage the smart wallet transactions and data fetching. Transaction gas fees are sponsored by Frak for standard SDK interactions. The paymaster handles gas sponsorship automatically through the Pimlico infrastructure. ## Communication side Since the WebAuthN standard is bounded to a specific domain, we use two principal ways of communication: 1. An **iFrame**, for bidirectional communication between the Frak Wallet and the implementing website. This is the primary communication channel used for all SDK actions (modals, embedded wallet, interactions, wallet status, etc.). 2. **URL-based redirection**, used specifically for SSO flows where the user needs to authenticate on the Frak Wallet domain. Working this way, with a **client first** approach, provides us a few key benefits: - We are not relying on third-party cookies - We don't rely on a centralised server to manage the communication, so you don't have to trust us with up-time, server provisioning, db going down or anything. - Your app can communicate with the client storage, even if the client is offline (so you can still fetch wallet address, transaction history etc. even if the client is offline) - All the frak related storage is stored on the client storage, in a secure way, and is only accessible by the frak wallet and allowed dApps. :::note On the centralisation side, yeah you are not relying on a centralised server, but you are relying on the frak website, **how is that different?** Firstly, the website hosting the Frak wallet is a PWA, meaning that user can install it on their devices (if compatible), and enjoy it everytime (even if our website come down for whatever reason). Secondly, it's all open source, meaning that you can easily redeploy it on your own infrastructure if you want to. ::: ### iFrame communication The iFrame communication side isn't that complex really. We are basically using an iFrame with a two-way communication (using regular `window.addEventListener('message', handler)`). The init flow is as follows: 1. The dApp create an iFrame with the right URL (can be built using an SDK helper or react component directly) 2. When the iFrame is loaded, it should be loaded on the **Frak query listener** page: no UI, just handling incoming message requests. 3. Once the frak query listener is loaded, and have warmed up a few key storage slots, it will send a `ready` message to the dApp. 4. Once the dApp receive the `ready` message, it can start sending message to the Frak Wallet, and receive message from it. On top of the classical postMessage communication, we added some abstraction around all of that, helping to have: - a `createIFrameFrakClient` method, that will build a `transport` (similar to [Viem transports](https://viem.sh/docs/clients/intro.html)) used for the communication - The `IFrameTransport` can handle every data types specified in the `IFrameRpcSchema`, - To query data via that transport directly, you can either: - Use the `request` method, returning a Promise of the expected `ReturnType` of the given request - Use the `listenerRequest` method, and passing a `callback` args, that will be invoked with the expected `ReturnType` of the given request, and every time the `ReturnType` change. Under the hood, both `request` and `listenerRequest` are using a small abstraction around `postMessage`, building a notification system, and a request/response system, on both sides. ### SSO redirect flow For SSO (Single Sign-On) authentication, the SDK uses a redirect-based flow: 1. The SDK builds a URL with compressed SSO parameters using `prepareSso` / `openSso` 2. The user is redirected to the Frak Wallet SSO page 3. The Frak Wallet handles authentication and creates the session 4. The user is redirected back to the dApp, and the SDK picks up the compressed SSO result from the URL ### Embedded wallet The embedded wallet (`displayEmbeddedWallet`) provides a persistent wallet UI that lives within the host page via the iFrame transport. It supports logged-in views (sharing, referred state) and logged-out views, all rendered within the Frak iFrame without any page redirects. Cross-origin WebAuthN via iFrame is an evolving w3c standard (see [this discussion](https://github.com/w3c/webauthn/issues/1656) for background). Browser support is tracked at: - [Chromium](https://issues.chromium.org/issues/40258856) - [Mozilla](https://github.com/mozilla/standards-positions/issues/964) - [WebKit](https://github.com/WebKit/standards-positions/issues/304) ### Communication security Since sensitive data can be shared between the dApp and the Frak Wallet, we built a secured communication layer. For data exchanged via URL (SSO params, referral context), the SDK uses: 1. JSON serialization of the message payload 2. A **sha256** validation hash of the primordial message keys (varies by message type) 3. Base64url encoding of the data + validation hash for URL-safe transport 4. On the receiving side, the data is decoded and the validation hash is verified against the payload For iFrame communication, the `postMessage` transport includes origin checks to ensure messages are only accepted from the expected Frak Wallet domain. :::note The hash validation mechanism is used for both iFrame communication and URL-based data exchange. ::: ## Transaction side Now, how does the transaction process work exactly? We won't enter in depth with the account abstraction way of working, since it's a bit out of the scope of this documentation, and samewise for the WebAuthN signing standard. Here is the flow when a user want to execute a transaction: 1. Build the transaction data 2. Prepare a `userOperation` bundle 3. Sign the `userOperation.hash` via the current webAuthN validator 4. Send the `userOperation` to the pimlico bundler, and receive the `userOpHash` 5. Wait for the `userOpHash` to be bundled in a transaction, and then wait for the `txHash` to be executed # Welcome to Frak > Turn your customers into advocates. Set up Frak on your store in about 5 minutes. No technical skills required for most platforms. import { LinkCard, Steps } from '@astrojs/starlight/components'; # Welcome to Frak Frak rewards your customers for sharing your store with friends, and rewards their friends for buying. It's word-of-mouth marketing that runs itself, and you only pay out when a real sale happens. Getting started takes about **5 minutes**. Pick the path that matches your store: ## What you'll set up 1. **Connect your store.** Link your shop to Frak so we can recognize your customers and the friends they refer. 2. **Add a share button.** Let customers share your products, and earn when their friends buy. 3. **Fund your rewards.** Add a budget by card. Rewards leave your balance only on real, confirmed purchases. ## You're in good hands - **No code for most stores.** Shopify, WordPress, and PrestaShop all have ready-made apps. - **You only pay for results.** Rewards are paid out only when a sale is confirmed. - **You stay in control.** Adjust your budget, rewards, and where buttons appear at any time. New to some of the words we use? The [glossary](/guides/glossary/) explains them in a minute. # Best practices > Simple ways to get more shares and more sales from Frak. Where to place prompts, how to set rewards, and how to keep momentum. import { Aside, CardGrid, LinkCard } from '@astrojs/starlight/components'; # Best practices Frak works best when customers are nudged to share at the right moment, with a reward worth talking about. None of this is complicated. Here's what makes the biggest difference. ## Ask at the moment of excitement The single best place to ask for a share is **right after checkout**, when your customer is happiest. Lead with the post-purchase card, then add the others: - **Post-purchase card**: shown straight after an order. This converts best, so set it up first. - **Share button on product pages**: lets customers share something specific they love. - **Welcome banner**: greets visitors who arrive from a friend's link, so they feel recognized. ## Bring in your existing customers Your email list is full of people who already like you. Drop your **newsletter sharing link** into a campaign email: one click opens your store with the sharing window ready and your rewards pre-filled. It's the fastest way to kick off a campaign on day one. ## Set rewards worth sharing - **Reward both sides.** A little reward for the friend who buys makes the link far more clickable. Frak suggests an **80/20 split** in the ambassador's favor, one tap to apply. - **Make it meaningful.** A reward big enough to mention ("get €6") travels further than a token amount. - **Match the reward to the goal.** Reward purchases for sales, sign-ups for leads. Pick the one goal that matters most for this campaign. ## Keep the momentum going - **Stay funded.** Campaigns pause when the budget runs dry. Keep a buffer so sharing never stops mid-stream. [Add funds](/guides/dashboard/configure/funds/). - **Re-engage your members.** Send an occasional [push notification](/guides/campaigns/push/) to announce a new campaign or product. The customers who already shared are your best ambassadors. - **Get discovered.** List your brand in the **Frak Explorer** so app users can find and share you. [Customize your listing](/guides/dashboard/configure/explorer/). ## Watch what works Open [Track performance](/guides/campaigns/performance/) to see which campaigns and placements drive the most shares and sales, then double down on the winners. # Create a campaign > Set up a Frak campaign in a short guided wizard. Choose your goal, budget, and rewards, then publish and go live. import { Steps, Aside, CardGrid, LinkCard } from '@astrojs/starlight/components'; # Create a campaign A campaign decides what your customers earn for sharing your store, and what action pays out. Setup is a short guided wizard, and you can **Save as draft** at any point and come back later. ## The wizard, step by step 1. **Campaign basics.** Give the campaign a title (only you see it) and pick the **merchant** it belongs to. You can keep your store's default reward currency, which is recommended, or choose another. 2. **Goal.** Pick the one action that triggers rewards: - **Sales**: reward purchases. The most popular choice for shops. - **Traffic**: reward visits to your site or app. - **Registration**: reward sign-ups and qualified leads. 3. **Territory & categories.** Choose the countries where your campaign runs. (Special advertising categories like credit or housing aren't supported yet, so you can move on.) 4. **Budget & schedule.** Set how much to spend and when. Pick a budget **period** (one global pot, or daily, weekly, monthly) and a **cap**. Then choose to start immediately, on a date, or over a fixed window. With no end date, the campaign simply runs until the budget is used up. 5. **Reward setup.** Decide how much customers earn and how it's calculated: - **Fixed amount**: the same reward per sale. - **% of basket**: the reward scales with order value. - **Tiered**: bigger baskets earn bigger rewards. You split the reward between the **ambassador** (your customer who shares) and the **referee** (the friend who buys). Frak suggests an 80/20 split in the ambassador's favor, one tap with **Apply reco**. 6. **Review & publish.** The last screen shows everything read-only so you can check it over. When it looks right, click **Publish**. ## You published, what happens next Your campaign goes live right away, and the Frak ambassador community gets a notification that you've launched, so sharing can start immediately. For the best results, give people somewhere to share from: # Track performance > See how your campaigns are doing in plain numbers: shares, sales, your real cost per result, and how it compares to paid ads. import { Aside, LinkCard } from '@astrojs/starlight/components'; # Track performance Once a campaign is live, the **Campaigns** area shows exactly how it's doing: who's sharing, what's selling, and what each result actually costs you. No spreadsheets, it updates on its own. ## The big picture The **Data overview** opens with the numbers that matter most: - **Ambassadors**: customers who shared your store. - **Shares**: how many times your store was shared. - **Generated revenue**: sales that came from those shares. - **Sharing rate**: how many people who saw the prompt actually shared. - **Avg. CPA**: your average cost per result. Below that you'll find a **sharing funnel** (from "share prompt seen" all the way to "converted"), **purchases generated** over time, a **projected revenue** trend, where shares come from (site vs the Frak app, mobile vs desktop), and your **top campaigns**. ## Your campaign list The **List** shows every campaign with its **status** (Active, Paused, Draft, Ended, or Archived) and key figures side by side: sharing rate, rewards paid, click-through rate, revenue, and budget spent. From the menu on each row you can **open performance**, **view parameters**, **edit**, **pause**, **resume**, **archive**, or **delete**. You can also select several at once to pause or archive them together. ## Inside a single campaign Open a campaign for the full story, organized in three tabs: - **Funnel & ROI**: the conversion funnel plus your return on investment. - **Ambassadors**: who's driving results, with a **top ambassadors** leaderboard (shares, sales, revenue, and what they earned). - **Configuration**: the campaign's settings, read-only. You'll also see a **cost breakdown** (how each reward splits between the ambassador, the referee, and Frak) and headline stats like the share of active ambassadors and how many referred friends converted. ## Export your data Need the raw numbers for your own reports? Use **Export** to download them. # Send push notifications > Reach the customers who joined your store with a push notification on their phone. Pick your audience, write your message, and send. import { Steps, Aside } from '@astrojs/starlight/components'; # Send push notifications Push notifications let you reach your **members**, the customers who joined by sharing your store, with a message straight to their phone. They're great for bringing people back: a new campaign, a fresh drop, or a seasonal nudge. ## Write and send 1. **Name it.** Give the notification an internal name (like "Summer reactivation"). Only you see this, your members never do. 2. **Write your message.** Add a **title** and a **message**. You can include an optional **image** and a **launch URL**, the page that opens when someone taps the notification. A live **preview** shows how it'll look. 3. **Choose your audience.** Pick which members should receive it. The dashboard shows how many people you'll reach as you adjust the selection. 4. **Pick when to send.** Choose **Send immediately**. (Scheduling for later is coming soon.) 5. **Review and send.** Check the audience and timing on the review screen, then **Send notification**. # What your customers see > A look at the customer side of Frak. How someone shares your store, how their friend buys, and how both get rewarded. import { Steps, Aside, CardGrid, LinkCard } from '@astrojs/starlight/components'; # What your customers see Here's the experience you're giving your customers, from the first share to money in the bank. Frak is word-of-mouth: your happy customers share your store with friends, the friends buy, and both sides earn a reward. No coupons to manage, no crypto knowledge needed on either side. There are two people in every story: - The **ambassador**: your customer, the one who shares. - Their **friend** (the referee): the one who clicks and buys. ## The journey, start to finish Say your campaign pays **€10 per sale**, split **€6 to the ambassador, €2 to the friend** (Frak keeps €2). 1. **Sarah buys from your store.** Right after checkout she sees a friendly card: "Share with a friend and you both earn." She taps it. 2. **Sarah shares her link.** Frak creates a personal link for her and she sends it to Tom on WhatsApp. 3. **Tom clicks and buys.** He lands on your store, sees he'll get a little reward too, and places a €50 order. 4. **You confirm the sale, both get paid.** Once the order is confirmed, **Sarah earns €6** and **Tom earns €2**, straight into their Frak wallet. 5. **Sarah gets a notification and comes back.** "You earned €6." So she shares again with the next friend. 6. **Tom collects his €2, and joins in.** He installs the Frak app, watches his reward land, and sees how simple it was. Now he shares your store with his own friends, and the loop starts over with him. Every friend who buys can become the next person sharing. That flywheel, share, buy, reward, repeat, is the whole point, and you only ever pay when a real sale happens. ## The free wallet, in plain terms Rewards land in a **Frak wallet**, which lives in the **Frak app**. Your customers don't need to know anything about crypto, and there's nothing scary here: - **Created in about 10 seconds.** No forms, no paperwork. - **Secured by Face ID or fingerprint.** No password to remember. - **Email is only used to recover the account.** Never for spam. - **Available on the App Store and Google Play.** A quick install means customers can reach and withdraw their money fast. ## How they get their money Customers always see exactly where a reward stands: - **Awaiting validation**: the reward is reserved while the order is being confirmed. - **To collect**: the sale is confirmed and the money is theirs. - **Cancelled**: if the order is refunded or cancelled, the reward is voided too, so you never pay for a sale that didn't stick. Once a reward is theirs, it lands **right in their Frak app**. From there they can **withdraw it straight to their bank account**, with no extra steps and nothing for you to handle. ## Where customers discover you Most sharing happens right on your store, through the buttons and cards you place. Customers can also find you in the **Frak Explorer**, a directory inside the Frak app where people browse brands worth sharing. Listing there is optional and free. ## Make it happen on your store # The business dashboard > Your home for everything Frak outside Shopify. Register your site, fund rewards, launch campaigns, and track results. import { Aside, CardGrid, LinkCard } from '@astrojs/starlight/components'; # The business dashboard The [business dashboard](https://business.frak.id/) is where you set up and run Frak. You register your site, fund your rewards, launch campaigns, and watch how they perform, all in one place. ## What you can do ## Finding your way around Once you open a merchant, the dashboard is organized into a few simple areas: - **My Merchants**: all your stores. Pick one to manage it, or add a new one. - **Campaigns**: create campaigns and follow their results, including a **Data overview** of everything at a glance. - **Members**: the customers who joined by sharing your store. Filter them and reach out. - **Push**: send a push notification to your members. - **Wallet**: your reward budget and payouts. - **Settings**: your account preferences, like language and currency. ## A typical first run # Merchant settings > Update your store's name and currency, allow extra domains, grab your newsletter sharing link, and check purchase tracking. import { Aside, LinkCard } from '@astrojs/starlight/components'; # Merchant settings Everything about your store lives under **Edit** for your merchant: its name and currency, the domains allowed to use it, a ready-made link for your newsletter, and the status of purchase tracking. ## Store details Update your **merchant name** and **default reward currency** any time. Your domain is shown here too. Click **Edit**, make your change, then **Save**. ## Allowed domains If your store runs on more than one address, add the extras under **Allowed domains** so Frak recognizes them all. A common case is a Shopify store that also uses its `myshopify.com` address. Type the domain (like `mystore.myshopify.com`), click **Add domain**, and save. Remove one any time with **Remove**. ## Newsletter sharing link Want to invite your existing customers to share? Copy your **newsletter sharing link** and drop it into any marketing email. When a customer clicks it, your storefront opens with the Frak sharing window ready, pre-filled with your current rewards, so they can share and earn in one tap. ## Purchase tracking The **Purchase tracker** shows whether Frak is receiving orders from your store, which is what lets campaigns reward real sales. You'll see the connection status, the platform in use, and when the last purchase came in. For most stores this is set up automatically by your platform app: # Customize appearance > Match Frak to your brand. Set your name, logo, and wording, and choose how your store appears in the Frak Explorer. import { Aside, LinkCard } from '@astrojs/starlight/components'; # Customize appearance Everything customers see from Frak can match your brand: the name and logo on the share button, the wording on each component, and how your store shows up in the Frak Explorer. You'll find it all under **Customize** for your merchant. ## Your brand identity These defaults apply everywhere Frak appears on your store: - **Name**: your brand name, shown to visitors. - **Logo**: displayed next to your name. - **Homepage link**: where visitors go when they click your name. - **Currency**: how reward amounts are shown. Leave on **Auto** to match the visitor. - **Language**: the language of Frak's text. **Auto** detects it from the visitor's browser. There's also a **Frak SDK displayed** switch. Turn it off to hide Frak from your storefront completely, without uninstalling anything. ## Wording for each component You can tailor the text on each Frak component to your voice: - **Share button**: the button label, with a version for when no reward applies. - **Banner**: the welcome message for referred visitors. - **Post-purchase card**: the prompt shown right after checkout. Pick the wording that fits your brand, preview it, and save. ## Appear in the Frak Explorer The **Frak Explorer** is where app users discover stores worth sharing. Listing your brand there is optional and free. - **Listed in Explorer**: turn your listing on or off. - **Hero image**: the main banner on your Explorer page (you can add a few more as a slider). - **Logo** and **Description**: a short, compelling pitch for why people should share you. # Add funds > Top up your reward budget so your campaigns can pay out. Add funds by card through Stripe, and turn payouts on or off any time. import { Aside, Steps } from '@astrojs/starlight/components'; # Add funds Your **reward budget** is the pot your campaigns pay rewards from. You top it up by card, and Frak only spends it when a real, confirmed sale happens. Nothing goes out until you fund it and switch payouts on. ## Set up your budget The first time, click **Set Up Budget**. This creates the budget your campaigns draw from. You only do it once per merchant. ## Add funds 1. Click **Add funds**. 2. Enter the amount and pay by card. **Stripe** handles the payment securely, so Frak never sees your card details. 3. Your new balance appears under **Reward Budget** once the payment clears. ## Turn payouts on or off A **Distributing Rewards** toggle controls whether active campaigns can pay out: - **On**: rewards are sent automatically as customers refer and buy. - **Off**: payouts pause. Your campaigns and balance stay exactly as they are, nothing is lost. ## Get money back Need to pull unused funds back? Turn **Distributing Rewards** off, then use **Withdraw funds**. Your available balance returns to your wallet. Rewards already promised to customers stay reserved, so you only ever withdraw what's truly free. # Team & roles > Invite teammates to help manage your store on Frak, and remove them when needed. All by Frak wallet address. import { Aside, Steps } from '@astrojs/starlight/components'; # Team & roles You can invite teammates to help run your store on Frak. Everyone is added by their Frak wallet address, and changes are confirmed with your fingerprint or face unlock, so only you can edit the team. ## The two roles - **Owner**: the account that registered the store. Full control, including the team and budget. - **Admin**: a trusted teammate who can manage the day-to-day, such as campaigns, funds, and appearance. That's the whole model. There's nothing complicated to assign. ## Add a teammate 1. Click **Add Team Member**. 2. Paste their **Frak wallet address** (it starts with `0x`). They can find it on their [Frak wallet settings page](https://wallet.frak.id/settings). 3. Click **Add member**, then **Save all changes** and confirm with your fingerprint or face unlock. ## Remove a teammate Click **Remove member** next to their name, then **Save all changes** and confirm. Changed your mind before saving? Use **Undo remove**. # Register your site > Add your site to Frak in a short two-step form. Enter your details, verify your domain with one DNS record, and confirm. import { Tabs, TabItem, Aside, CardGrid, LinkCard } from '@astrojs/starlight/components'; # Register your site Adding your site to Frak is a short, two-step form. You enter a few details, prove the site is yours with one DNS record, and confirm. It takes a few minutes, and you only do it once. ## Add your details In the [business dashboard](https://business.frak.id/), start a new site. On the **Add merchant details** screen, fill in: - **Merchant Name**: your store or brand name. This is what customers see. - **Currency**: the currency your rewards are paid in. Most merchants keep the default (**EURe**). - **Domain Name**: your website address, like `example.com`. - **Setup Code**: optional. Leave it blank unless Frak gave you one. ## Verify your domain This proves the site is yours, so no one else can claim it. As soon as you enter your domain, Frak shows a **DNS TXT record**. Copy it, add it at your domain provider, and you're verified. Pick your provider for the exact clicks: 1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com) and select your domain. 2. In the sidebar, open **DNS → Records**. 3. Click **Add record**. 4. Set **Type** to **TXT**, **Name** to `@`, and paste the record into **Content**. 5. Leave **TTL** on **Auto** and click **Save**. Cloudflare usually applies TXT records within minutes. 1. Log in to the [OVHcloud Control Panel](https://www.ovh.com/manager/) and open **Web Cloud → Domain names**. 2. Select your domain, then open the **DNS zone** tab. 3. Click **Add an entry** and choose **TXT**. 4. Leave **Sub-domain** empty (for your root domain) and paste the record into the **Value** field. 5. Click **Next**, then **Confirm**. OVHcloud publishes the record after a short delay. 1. Log in to the [Infomaniak Manager](https://manager.infomaniak.com) and open **Domain names**. 2. Select your domain and open the **DNS zone**. 3. Click **Add a record** and choose **TXT**. 4. Leave the **Source** empty or set it to `@`, then paste the record into the **Target** field. 5. Click **Save** to apply your changes. 1. Sign in to GoDaddy and open **My Products**. 2. Next to your domain, select **DNS** (or **Manage DNS**). 3. In the **Records** section, click **Add** and choose **TXT**. 4. Set **Name** to `@` and paste the record into **Value**; leave **TTL** on the default. 5. Click **Save**. 1. Sign in to Namecheap and open **Domain List**, then **Manage** next to your domain. 2. Open the **Advanced DNS** tab. 3. Click **Add New Record** and choose **TXT Record**. 4. Set **Host** to `@` and paste the record into **Value**; leave **TTL** on **Automatic**. 5. Click the green check to save the record. 1. Sign in to your domain provider, usually where you bought the domain or host your site. 2. Find the DNS area. It may be called **DNS management**, **DNS zone**, **Advanced DNS**, or **Name server management**. 3. Add a new record with **Type** set to **TXT**. 4. Put `@` (or the host shown by Frak) in the **Name / Host** field, and paste the record into the **Value** field. 5. Save your changes. If you can't find the DNS settings, contact your provider's support. When the record is in, click **Continue**. Frak checks it for you. ## Confirm and register On the **Merchant registration** screen, review the **Summary** (your name, domain, and currency). When it looks right, click **Complete Registration** and approve with your fingerprint or face unlock. No password to remember. That's it, usually in under a minute. Your site is registered and ready. ## You're registered, what's next ## If something looks off - **"A merchant already exists for this domain."** Your site is already registered, possibly under another account. Reach out from the [business dashboard](https://business.frak.id/) if that's unexpected. - **"The DNS TXT record is not set."** The record isn't visible yet. Double-check you pasted the exact value at your provider, then wait a few minutes and click **Continue** again. # Common questions > Quick answers to the questions merchants ask most about Frak. Crypto, costs, refunds, control, and privacy. import { Aside, LinkCard } from '@astrojs/starlight/components'; # Common questions Short, straight answers to what merchants ask most before going live. ## Your customers **Do my customers need crypto, or a wallet, to take part?** No. They create a free Frak wallet in about 10 seconds with Face ID or a fingerprint, no crypto knowledge, no jargon, no money up front. See [what your customers see](/guides/customer-journey/). **Is this really my customers, or strangers?** It's your real customers and the friends they personally invite. That's warm, trusted word-of-mouth, not cold ads. **Can customers actually cash out their rewards?** Yes. They can transfer their earnings to their bank account from the wallet whenever they like. ## Costs and payments **How much does Frak cost?** Frak takes a **20% commission** on your campaign budget. The other 80% goes to your customers as rewards. You only pay on real, confirmed sales. **When are rewards actually paid?** Only when a sale is confirmed. Until then the reward is held as "awaiting validation", so nothing leaves your budget for an order that isn't final. **What happens if an order is refunded?** The matching reward is cancelled automatically. You never pay for a sale that didn't stick. **Can I control my spending?** Yes. Set a budget cap (overall, or daily, weekly, monthly), pause a campaign any time, or switch reward payouts off entirely. [Add funds](/guides/dashboard/configure/funds/). **Which currencies can I use?** EUR, USD, or GBP via Monerium, or USDC via Circle. Most merchants keep the default (EURe). ## Setup and privacy **Do I need to write code?** Not for Shopify, WordPress, or PrestaShop, they all have ready-made apps. A fully custom site needs a little setup. [Pick your platform](/guides/). **How long does setup take?** About 5 minutes for most stores: install, connect, fund, and launch. **Is my customers' data safe?** Yes. A customer's email is only ever used to recover their wallet, never for unsolicited messages. # Glossary > The handful of words Frak uses, explained in plain language. # Glossary A quick guide to the words you'll see across Frak. Most of them describe everyday ideas: a store, a customer who shares, the friend who buys. ## Merchant Your store on Frak: a website or domain where you run campaigns. You can manage several merchants from one account. [Register your site](/guides/dashboard/register/). ## Ambassador A customer who shares your store with friends. When their share leads to a sale (or another action you chose), they earn a reward. Ambassadors are sometimes called referrers. ## Referee The friend who arrives through an ambassador's link and buys. Referees can earn a reward too, which is a great reason to click. ## Campaign A set of rules for what customers earn and what triggers it. You choose a goal (sales, traffic, or registrations), a budget, and the rewards. [Create a campaign](/guides/campaigns/create/). ## Reward budget The pot your campaigns pay rewards from. You top it up by card, and Frak only spends it on real, confirmed actions. [Add funds](/guides/dashboard/configure/funds/). ## Reward model How a reward is calculated: a **fixed amount**, a **percentage of the basket**, or **tiered** (bigger baskets earn more). You set this when you create a campaign. ## CPA (cost per action) What you pay for one confirmed result, like a sale. Frak shows your average CPA so you can see your real cost, and how it compares to paid ads. ## Members The customers who joined by sharing your store. You can filter them into groups and reach out. [Send push notifications](/guides/campaigns/push/). ## Push notification A short message you can send to your members' phones, for example to announce a new campaign or product. ## Explorer A directory in the Frak app where users discover stores worth sharing. Listing your brand there is optional. [Customize how you appear](/guides/dashboard/configure/explorer/). ## Wallet A free Frak account, secured by fingerprint or face unlock instead of a password. You use one to manage your store, and your customers use one to collect their rewards. ## Domain verification A one-time check that proves a domain is yours, done by adding a small DNS record. It's part of registering your site. [How it works](/guides/dashboard/register/). # Get started on WordPress, PrestaShop or a custom site > Three simple steps, register your site, install Frak, and set up your rewards from the business dashboard. import { Steps, Aside, LinkCard, CardGrid } from '@astrojs/starlight/components'; # Get started on WordPress, PrestaShop or a custom site Not on Shopify? No problem. For WordPress, PrestaShop, and custom-built sites, setup is **three short steps**: register your site, install Frak, and set up your rewards. Most of it happens in your [business dashboard](https://business.frak.id/), the home for everything outside Shopify. ## The three steps 1. **Register your site.** Sign in to the [business dashboard](https://business.frak.id/) and add your website. To prove the site is yours, you'll add a small verification record at your domain provider, a one-time check that takes a couple of minutes. See [Register your site](/guides/dashboard/register/). 2. **Install Frak on your site.** Pick your platform below and follow the matching guide. 3. **Set up your rewards.** Back in the business dashboard, [add a budget](/guides/dashboard/configure/funds/) and [create your first campaign](/guides/campaigns/create/). This is where you fund rewards and decide how much customers earn. ## Step 2: install Frak on your site ## What you'll manage in the dashboard # Add Frak to a custom website > Add Frak to any custom-built site with a few lines of code, then confirm real orders with a signed webhook from your backend. import { Tabs, TabItem, Steps, Aside, LinkCard, CardGrid } from '@astrojs/starlight/components'; # Add Frak to a custom website For a custom-built site, adding Frak takes two parts: 1. **Add the Frak components to your site.** Load Frak, set one config object, and drop in the share button, the welcome banner, and the post-purchase card. Pick the setup that matches your stack below. 2. **Validate purchases from your backend.** Confirm real orders with a signed webhook, so rewards only go out on genuine sales. ## The components All three components are framework-agnostic [web components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components), so they work the same whether you write plain HTML, use a bundler, or build with React. | Component | Where it goes | What it does | | --- | --- | --- | | `` | Product page, homepage | Lets customers share your store and earn rewards | | `` | Top of the page | Welcomes referred visitors | | `` | Order confirmation page | Prompts a share right after checkout, and tracks the order | ## 1. Add Frak to your site ### Load and configure Frak Add this to the `` of your pages. The config object is read by Frak when it loads, so set it **before** the script tag. ```html title="index.html" ``` ### Add the components Place the banner near the top of your ``, and the share button wherever you want customers to share: ```html ``` ### Track the purchase On your order confirmation page, add the post-purchase card with your order details. When `customer-id`, `order-id`, and `token` are all present, the card also registers the order with Frak automatically: ```html ``` If you do not want to show the card, register the order directly instead. The action becomes available once Frak is ready: ```html ``` ### Install ```bash npm install @frak-labs/components @frak-labs/core-sdk ``` ### Configure Frak Set the config in its own module so it runs first: ```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", }, }, }; ``` ### Register the components Import your config module first, then import each component you use. Importing a component registers its custom element and boots the SDK from `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"; ``` Then drop the elements into your markup, exactly like the HTML tab: ```html ``` ### Track the purchase The post-purchase card tracks the order automatically when given all three attributes. To track without rendering the card, call the action directly: ```ts import { trackPurchaseStatus } from "@frak-labs/core-sdk/actions"; await trackPurchaseStatus({ customerId: "cust_123", orderId: "order_456", token: "a-unique-order-token", }); ``` The visual components are the same web components, used inside JSX. Install them and (optionally) `@frak-labs/core-sdk` for direct action calls: ```bash npm install @frak-labs/components @frak-labs/core-sdk ``` ### Configure and register Set the config in its own module, then import it (and the components) before you render your app: ```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(); ``` ### Use the components in JSX ```tsx title="App.tsx" export function App() { return ( <> {/* On your order confirmation route */} ); } ``` The post-purchase card tracks the order automatically. To track without the card, call `trackPurchaseStatus` from `@frak-labs/core-sdk/actions` after the order is placed. ## 2. Validate purchases from your backend Tracking on the page tells Frak an order *might* be coming. Rewards only fire once your backend confirms the order is real with a signed webhook. This keeps rewards tied to genuine, paid sales. 1. **The page registers the order.** The post-purchase card (or `trackPurchaseStatus`) sends `customerId`, `orderId`, and `token` so Frak starts listening for that order. 2. **Your backend confirms it.** When the order is paid (or refunded, cancelled), your server sends a webhook to Frak with the same identifiers and an HMAC signature. 3. **Frak triggers the reward.** Once the signature checks out and the status is `confirmed`, Frak sends the `PurchaseCompleted` interaction, which can pay out rewards based on your active campaigns. Your webhook URL and signing secret are in the [business dashboard](https://business.frak.id/), under the **Purchase Tracker** section of your merchant. Sign the entire request body with HMAC SHA-256 and send it in the `x-hmac-sha256` header. ```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', ]); ``` See the [Purchase webhook reference](/developers/api/webhook/) for the full payload (including line items) and the [track purchase endpoint](/developers/api/track-purchase/) for the page-side call. ## Next steps # Install Frak on PrestaShop > Add Frak to your PrestaShop store in three simple steps. Install the module, paste one key, and start rewarding customers for sharing. import { Steps, Aside, LinkCard, CardGrid } from '@astrojs/starlight/components'; # Install Frak on PrestaShop Adding Frak to PrestaShop takes about five minutes. You install a module, paste one key from your dashboard, and Frak starts tracking referrals and rewards. The buttons even appear on the right pages on their own. ## Install the module 1. Download the latest **Frak module** from the [releases page](https://github.com/frak-id/wallet/releases?q=PrestaShop+Module&expanded=true). It's the `frakintegration-.zip` file. 2. In your back office, go to **Modules → Module Manager → Upload a module** and drop the zip in. 3. Click **Configure** on the **Frak** module to open its settings. ## Connect your store This is the only key you'll ever copy. It links your store to your Frak account. 1. In the [business dashboard](https://business.frak.id/), open your store and go to **Purchase Tracker**. Select **PrestaShop**, click **Register**, and copy the key it shows you. 2. On the Frak settings page, scroll to **Purchase Tracking → Webhook Secret** and paste the key. 3. Check that the **Merchant** line shows a green **Connected** badge, then click **Save Settings**. That's it. Your store is connected, and Frak starts tracking orders right away. ## You're live, now make it shine The share button, banner, and post-purchase card appear automatically on the right pages. From here you can fine-tune where they show, fund your rewards, and launch a campaign. # Choose where Frak buttons appear on PrestaShop > Turn each Frak component on or off and adjust where it shows on your PrestaShop storefront. import { Aside, LinkCard } from '@astrojs/starlight/components'; # Choose where Frak buttons appear on PrestaShop Once Frak is [installed and connected](/guides/platforms/prestashop/), the three components already show on the right pages. You can turn any of them off or fine-tune them from the **Component Placements** panel on the Frak settings page. | Component | Where it shows | On by default | Options | | --- | --- | --- | --- | | **Share button** | Product pages | Yes | Button style: Primary, Secondary, or None | | **Banner** | Top of the storefront | Yes | Custom CSS class | | **Post-purchase card** | Order confirmation page | Yes | None | | **Post-purchase card** | Customer order details | Yes | None | Each placement is a simple checkbox. Uncheck the ones you don't want, then **Save** to apply. ## Put a component somewhere else Need Frak on a page the checkboxes don't cover, like a CMS page or a custom block in your theme? Use the bundled Smarty tags in any `.tpl` file: ```smarty {frak_banner placement="hero" referral_title="Welcome back!"} {frak_share_button text="Share & earn up to {REWARD}" no_reward_text="Share & earn" placement="sidebar"} {frak_post_purchase variant="referrer" cta_text="Earn rewards"} ``` ## Buttons not showing? Confirm the placement is checked in **Component Placements**, then clear your cache (**Advanced Parameters → Performance → Clear cache**). Some themes remove the product or header hooks Frak uses, so if a checked placement still shows nothing, check that theme template. Full steps are in [Settings & tracking](/guides/platforms/prestashop/details/). ## Next # PrestaShop settings & tracking > Requirements, brand fields, order tracking, the retry queue, and troubleshooting for the Frak PrestaShop module. import { Aside, Tabs, TabItem, LinkCard } from '@astrojs/starlight/components'; # PrestaShop settings & tracking The reference for everything beyond the [basic setup](/guides/platforms/prestashop/): requirements, brand fields, how order tracking keeps itself reliable, and what to do when something looks off. ## Requirements - **PrestaShop 8.1+** with **PHP 8.1+**. - The module ships everything it needs inside the zip. There's nothing to install on a command line. ## Brand fields The **Website Information** panel sets what customers see in the Frak window: - **Shop Name**: defaults to your PrestaShop shop name. Used as the title. - **Logo**: paste a public **Logo URL**, or use **Or upload a file** (JPG, PNG, GIF, or SVG up to 2 MB). The preview on the right updates as you type. The rest of the wording and translations are managed from the [business dashboard](https://business.frak.id/). Click **Save Settings** when done. ## How order tracking stays reliable When an order's status changes, the module tells Frak so rewards go out on real sales. If a message can't get through, it's saved and retried automatically (up to 5 times, spaced further apart each time). To make sure those retries actually run, set up one of the two options below. Install the official **ps_cronjobs** module from the Module Manager. Frak registers itself automatically, and the **Retry Cron** line on the settings page turns green. Nothing else to do. The **Retry Cron** line shows a ready-made URL. Add it to a cron that runs every 5 minutes, for example with `crontab -e`: ```cron */5 * * * * curl -fs 'https://your-shop.example/index.php?fc=module&module=frakintegration&controller=cron&token=' ``` The URL includes a private token from your settings page, so keep it to yourself. You can also run a retry on demand: open **Maintenance → Webhook queue** and click **Drain queue now**. ## Keep an eye on the queue The **Maintenance → Webhook queue** panel shows the health of order tracking at a glance: - **Pending**: waiting for the next attempt. - **Delivered**: sent successfully. - **Parked (failed)**: gave up after retrying. A red badge appears if this isn't zero. - **Last error**: the most recent problem, with a timestamp. ### Which order statuses count Orders that reach **Awaiting payment validation**, **Payment accepted**, **Delivered**, or **Awaiting payment (out of stock)** are tracked as confirmed sales. **Cancelled** and **Payment error** mark the sale as cancelled, and any refund (including partial refunds and returns) marks it as refunded. **Preparation in progress** and **Shipping** are ignored on purpose, so they don't clutter your results. ## Troubleshooting - **Merchant says "Not resolved for this domain".** Confirm your store's domain is registered on the [dashboard](https://business.frak.id/), then open **Maintenance** and click **Refresh Merchant**. (Your main domain works automatically; only subdomains need adding.) - **Deliveries failing right after setup.** Re-copy the key from **Purchase Tracker → PrestaShop** in the dashboard, paste it back into **Webhook Secret**, and click **Save Settings**. - **Parked count keeps growing.** Open **Advanced Parameters → Logs** and filter on `FrakIntegration`. The **Last error** line on the queue panel usually points straight at the cause. - **Buttons missing on the storefront.** Confirm the placement is enabled in [Component Placements](/guides/platforms/prestashop/components/) and clear your cache (**Advanced Parameters → Performance → Clear cache**). ## For developers The Frak PrestaShop module is open source, inside the [Frak wallet monorepo](https://github.com/frak-id/wallet) under `plugins/prestashop`. Open an issue or a pull request any time. # Install Frak on WordPress > Add Frak to your WordPress store in three simple steps. Install the plugin, paste one key, and start rewarding customers for sharing. import { Steps, Aside, LinkCard, CardGrid } from '@astrojs/starlight/components'; # Install Frak on WordPress Adding Frak to WordPress takes about five minutes. You install a plugin, paste one key from your dashboard, and you're ready to reward customers for sharing your store. It works with any theme, with or without WooCommerce. ## Install the plugin 1. Download the latest **Frak plugin** from the [releases page](https://github.com/frak-id/wallet/releases?q=wordpress+plugin&expanded=true). It's the `frak-integration.zip` file. 2. In your WordPress admin, go to **Plugins → Add New Plugin → Upload Plugin**. 3. Pick the zip file, click **Install Now**, then **Activate**. ## Connect your store This is the only key you'll ever copy. It links your store to your Frak account. 1. In the [business dashboard](https://business.frak.id/), open your store and go to **Purchase Tracker**. Select **WooCommerce**, click **Register**, and copy the key it shows you. 2. In WordPress, go to **Settings → Frak** and paste the key into **Webhook Secret**. 3. Check that the **Merchant** line shows a green **Connected** badge, then click **Save Settings**. That's it. Your store is connected. ## You're live, now make it shine # Add Frak buttons on WordPress > Place the Frak share button, banner, and post-purchase card on your WordPress pages with a block, shortcode, widget, or Elementor widget. import { Tabs, TabItem, Aside, LinkCard } from '@astrojs/starlight/components'; # Add Frak buttons on WordPress Once Frak is [installed and connected](/guides/platforms/wordpress/), you choose where your customers see it. There are three Frak components, and you can add each one the way that fits your theme: a block, a shortcode, a widget, or an Elementor widget. | Component | What it does | | --- | --- | | **Share button** | Lets customers share your store and earn rewards. | | **Banner** | Welcomes referred visitors at the top of the page. | | **Post-purchase card** | Invites customers to share right after they buy. | ## Add a component Pick the method that matches how you edit your site. 1. Open the post, page, or template part in the editor (for block themes: **Appearance → Editor**). 2. Click the **+** where you want the component and search for **Frak**. 3. Choose **Frak Share Button**, **Frak Banner**, or **Frak Post-Purchase**. 4. Adjust the options in the sidebar, then save. Paste the matching shortcode into any page, post, or builder that accepts shortcodes: ```text [frak_share_button text="Share and earn!"] [frak_banner] [frak_post_purchase variant="referrer"] ``` From a theme template you can also call it in PHP: ```php echo do_shortcode( '[frak_share_button text="Share & earn"]' ); ``` Go to **Appearance → Widgets**, pick the sidebar or footer area, and add **Frak Share Button**, **Frak Banner**, or **Frak Post-Purchase**. Each one has a simple form with the same options as the block. If your site uses **Elementor**, the plugin adds a **Frak** category in the editor. Drag **Frak Share Button**, **Frak Banner**, or **Frak Post-Purchase** onto the canvas and tune the controls on the right. ## Block, shortcode, and widget names If you need the exact identifiers (for a page builder search or a template), here they are: | Component | Block | Shortcode | Widget | | --- | --- | --- | --- | | Share button | `frak/share-button` | `[frak_share_button]` | Frak Share Button | | Banner | `frak/banner` | `[frak_banner]` | Frak Banner | | Post-purchase card | `frak/post-purchase` | `[frak_post_purchase]` | Frak Post-Purchase | ## Next # WordPress settings & webhooks > Requirements, brand fields, WooCommerce order tracking, delivery logs, and troubleshooting for the Frak WordPress plugin. import { Aside, LinkCard } from '@astrojs/starlight/components'; # WordPress settings & webhooks The reference for everything beyond the [basic setup](/guides/platforms/wordpress/): requirements, brand fields, order tracking, and what to do when something looks off. ## Requirements - **WordPress 6.4+** and **PHP 8.0+**. - **WooCommerce** is optional. You only need it for purchase tracking, and the plugin is HPOS-compatible. ## Brand fields In **Settings → Frak**, under **Website Information**, you can set what customers see in the Frak window: - **App Name**: defaults to your site name. Click **Use Site Name** to fill it. - **Logo URL**: defaults to your site icon. Click **Use Site Icon**, or upload your own. The rest of the wording and translations are managed from the [business dashboard](https://business.frak.id/), so the WordPress page only covers these two fields. Click **Save Settings** when done. ## Order tracking with WooCommerce After you paste your key and save, the **WooCommerce Webhook** section lets Frak know when an order is placed, so rewards go out on real sales. 1. Click **Set up webhook**. (It stays disabled until your merchant is connected and the key is saved.) 2. Look for the green banner: **WooCommerce webhook active**. The **Secret in WooCommerce** line should read **matches the secret saved above**. That's the whole setup. WooCommerce handles retries and delivery on its own, so you don't have to maintain anything. If the banner is yellow instead of green, the message tells you exactly what's off and which button to click (**Re-enable webhook**, **Sync webhook**, and so on). ## Troubleshooting - **Merchant says "Not resolved for this domain".** Add your site's domain under **Allowed Domains** on the [dashboard](https://business.frak.id/), then click **Refresh Merchant** on the plugin settings page. (Your main domain works automatically; only subdomains need adding.) - **Tracking stopped after a domain change.** Same fix: add the new domain, then click **Refresh Merchant**. The webhook re-points itself automatically. - **"Secret does not match".** Re-copy the key from **Purchase Tracker → WooCommerce** in the dashboard, paste it back in **Settings → Frak**, save, then click **Sync webhook**. - **"Vendor folder missing" notice.** You unzipped a developer copy instead of the packaged release. Download `frak-integration.zip` from the [releases page](https://github.com/frak-id/wallet/releases?q=wordpress+plugin&expanded=true). ## For developers # Get started with Shopify > Install the Frak app, connect your store, and go live with referral rewards, all from one place, in about 5 minutes. import { Steps, Aside, LinkCard, CardGrid } from '@astrojs/starlight/components'; # Get started with Shopify Everything you need for Shopify lives inside **one app**. You install it, follow a short guided setup, and you're ready to reward customers for spreading the word. No separate dashboards, no code to copy. ## Before you start - An active Shopify store you can sign in to as an admin. - A few minutes to follow the in-app setup. You don't need a crypto wallet beforehand. You'll create your free Frak account during setup. ## Set it up 1. **Install the Frak app.** Open the [Frak app on the Shopify App Store](https://apps.shopify.com/frak) and click **Add app**. Shopify adds it to your store and opens the Frak setup screen. {/* screenshot: /img/guides/shopify/getting-started/01-install-app.png */} 2. **Connect your Frak account.** The first screen asks you to connect with a Frak wallet. This is your free Frak account. - **New to Frak?** Choose **Create an account** and follow the secure sign-up. It uses your device's fingerprint or face unlock, with no password to remember. - **Already have an account?** Choose **I already have an account** and sign in. Both options take you through the Frak sign-in screen, then back into the app. {/* screenshot: /img/guides/shopify/getting-started/02-connect-wallet.png */} 3. **Run the guided setup.** The app walks through five quick checks and confirms each one for you. The first four happen automatically; the last opens your theme editor, where you toggle Frak **on** and click **Save**. {/* screenshot: /img/guides/shopify/getting-started/03-guided-setup.png */} That's it. Your store is connected and ready. ### What the guided setup does You don't need to understand the details, but here's what's happening behind each check: | Setup check | What it does for you | | --- | --- | | **Connect your store** | Creates your store on Frak so rewards can be tracked. | | **Turn on tracking** | Recognizes customers who arrive from a friend's link. | | **Send purchases to Frak** | Lets Frak know when an order is placed. | | **Secure your purchases** | Confirms orders are genuine, so rewards only go out on real sales. | | **Activate Frak in your theme** | Switches Frak on across your storefront. | ## You're live, now make it shine Your store is connected. Next, add the buttons your customers will use and fund your rewards: ## Need a hand? - Each setup step shows its own status and hints inside the app. - For deeper analytics and settings, open the [business dashboard](https://business.frak.id/) with the same account. - The Frak Shopify app is [open source](https://github.com/frak-id/wallet). Report an issue or contribute any time. # Customize appearance (Shopify) > Adjust your brand name, logo, and the wording shown to customers. import { Aside } from '@astrojs/starlight/components'; # Customize appearance Make Frak feel like part of your brand. Open the **Appearance** tab in the Frak app, where everything is organized into a few sub-tabs: - **Text Customizations**: your **logo** and the **wording** shown in share prompts and reward messages. - **Share Button** and **Banner**: turn each placement on and configure where it appears on your storefront. - **Checkout Extension**: the post-purchase card shown on the checkout thank-you and order status pages. - **Explorer**: how your store appears in the **Frak Explorer**, where customers discover brands. {/* screenshot: /img/guides/shopify/appearance/01-appearance-tab.png */} Coming soon: detailed steps and screenshots. # Add sharing buttons (Shopify) > Add the share button and post-purchase card to your Shopify storefront. import { Aside } from '@astrojs/starlight/components'; # Add sharing buttons Once your store is connected, add the buttons customers use to share and earn. From your Shopify theme editor you can add: - **Share button** on your product pages, so customers can share and earn referral rewards. - **Post-purchase card** on the order status / thank-you page, shown right after checkout. **We recommend this one** because it converts best. - **Banner** to promote active rewards across your storefront. Each is a Shopify theme block, and the Frak app deep-links you to the right spot, so there's no code to copy. {/* screenshot: /img/guides/shopify/buttons/01-theme-blocks.png */} Coming soon: detailed steps and screenshots for each placement. # Create a campaign (Shopify) > Decide how much customers earn for referrals and purchases. import { Aside } from '@astrojs/starlight/components'; # Create a campaign A campaign sets the rules for rewards: how much a customer earns when a friend clicks, signs up, or buys. You can create one from the **Campaigns** tab in the Frak app, or in the [business dashboard](https://business.frak.id/) for more options. {/* screenshot: /img/guides/shopify/campaigns/01-campaign-tab.png */} The full walkthrough lives in [Create a campaign](/guides/campaigns/create/). Coming soon: a Shopify-specific walkthrough with screenshots. # Add funds (Shopify) > Top up your Frak reward balance, billed directly through Shopify. import { Aside } from '@astrojs/starlight/components'; # Add funds Rewards are paid from your Frak balance. On Shopify you top it up straight from the app. The charge goes through your usual **Shopify billing**, so there's no separate checkout or invoice to manage. Open the **Funding** tab in the Frak app, choose an amount, and confirm. Your balance updates once the payment clears. {/* screenshot: /img/guides/shopify/funds/01-financing-tab.png */} Coming soon: detailed steps and screenshots.