Automatic Attribution on Base
Once your project is registered on Base Dashboard, the Base App will auto-append your Builder Code to transactions its users make in your app (e.g. via your app, or the Base App’s browser). This attributes that activity to your project and qualifies you for potential future rewards.Integrating Outside the Base App
If users also access your app on the web or through other clients, you’ll need to integrate thedataSuffix parameter to capture that activity.
When you register a project on Base Dashboard, you will receive a Builder Code—a random string (e.g., bc_b7k3p9da) that you’ll use to generate your attribution suffix. The recommended approach is to configure dataSuffix at the client level, which appends your Builder Code to all transactions.
Quick Setup with Wagmi
1
Install Dependencies
Install the required packages. Requires viem version
2.45.0 or higher.Install Wagmi attribution dependencies
2
Configure Your Wagmi Client
Add the
dataSuffix option to your Wagmi config. This automatically appends your Builder Code to all transactions.config.ts
3
Use Wagmi Hooks as Usual
With the config in place, all transactions automatically include your Builder Code—no changes to your hooks or components. This works with both
useSendTransaction and useSendCalls.App.tsx
Quick Setup with Viem
1
Install Dependencies
Install the required packages. Requires viem version
2.45.0 or higher.Install Viem attribution dependencies
2
Configure Your Wallet Client
Add the
dataSuffix option when creating your wallet client. See the viem wallet client docs for more configuration options.client.ts
3
Send Transactions as Usual
All transactions sent through this client automatically include your Builder Code.
send-transaction.ts
Using CDP Wallets
Coinbase Developer Platform (CDP) Wallets support Builder Codes on user operations from smart accounts. PassdataSuffix when you send a user operation so your Builder Code is appended; no contract changes required. This works across the React hooks (useSendUserOperation), Node (TypeScript), and Python SDKs.
See Builder Codes in the CDP Wallets documentation for setup instructions, including how to generate the suffix with Attribution.toDataSuffix from ox/erc8021.
Using Privy
Privy provides adataSuffix plugin that automatically appends your Builder Code to all transactions—including both EOA transactions and ERC-4337 smart wallet user operations.
See the Privy Builder Codes integration guide for setup instructions.
Legacy: Per-Transaction Approach
Appending dataSuffix Per-Transaction
Appending dataSuffix Per-Transaction
If you need to append the suffix on a per-transaction basis rather than at the client level, you can pass
dataSuffix directly to the transaction.- useSendTransaction
- useSendCalls
App.tsx
Verify Attribution
To confirm your Builder Code is being appended correctly: 1. Use a Block Explorer (Basescan, Etherscan, etc.)- Find your transaction hash
- View the input data field
- Verify the last 16 bytes are the
8021repeating - Decode the suffix to confirm your Builder Code is present
- Use the Builder Code Validation tool
- Select transaction type
- Enter the transaction or UserOperation hash
- Click the Check Attribution button
Track User Analytics
Builder Codes tell you which onchain transactions came from your app. To measure active users, retention and conversion, join that onchain data with the signals your app already sees when someone opens it, connects a wallet and sends a transaction. This section shows where each signal comes from and how to read it. Where you store the data and which analytics stack you use is up to you.1
Identify Users by Wallet Address
The connected wallet address is the key that joins in-app activity to onchain activity. Read it from the wallet’s EIP-1193 provider, which every wallet library exposes, and normalize it to lowercase so the same address always matches.For smart accounts, this is the smart contract account address. Onchain, it appears as the
identify-wallet.ts
sender of each UserOperation, not as the from of the outer transaction (see step 3).2
Capture In-App Signals at Each Journey Stage
Each stage of the funnel has a signal your app can read directly. Store each one with the wallet address and a timestamp.
Record the transaction hash and the action it performs in your app (for example, mint, swap or deposit) at submit time. The hash is what links an in-app action to its onchain outcome.
resolve-call-bundle.ts
3
Read Transaction Outcomes Onchain
Onchain data is the source of truth for whether a transaction happened, who sent it and whether it carried your Builder Code. Where each field lives depends on the account type:To backfill history, or to catch transactions sent outside your app’s UI, scan Base blocks (or your contracts’ logs with
The ERC-8021 suffix sits at the end of the calldata and reads backwards: the 16-byte marker
0x80218021802180218021802180218021, then a 1-byte schema ID, then a 1-byte length, then the comma-separated codes as ASCII. For example, bc_b7k3p9da produces the suffix 0x62635f62376b33703964610b0080218021802180218021802180218021. Match on the decoded codes rather than the raw bytes, because a wallet can add its own code next to yours.The function below takes a transaction hash recorded in step 2 and returns one row per user action, for both account types. It uses Viem and ox, which are already used on this page; any RPC client works the same way.get-attributed-activity.ts
eth_getLogs) for calldata that ends with the ERC-8021 marker, and decode each match the same way.4
Compute the Metrics
Join the in-app signals from step 2 with the onchain rows from step 3 on the lowercased wallet address, and on the transaction hash for the submit and success stages. Then:
- Active users: count distinct addresses per UTC day, week or month. Report connected users and transacting users (at least one row with
successandattributedboth true) separately, since the gap between them is your activation rate. - Retention: assign each address to a cohort by the week of its first successful attributed transaction, then measure the share of each cohort that transacts again 1, 7 and 30 days later.
- Funnel: count addresses that reach each stage (open → connect → submit → success), split by acquisition source. Drop-offs between submit and success split into rejected signatures (error code
4001), reverted transactions (successis false) and transactions without your Builder Code (attributedis false), which usually means a client is not configured withdataSuffix.