Conversion Registration
This guide explains how to programmatically register a conversion with SoyCap.io, which is essential for tracking conversions associated with your affiliate campaigns. The process involves retrieving transaction details via the SoyCap.io API and then signing the transaction using the campaign owner’s keypair using @solana/web3.js
.
Prerequisites
- Merchant Authentication: Ensure you have an
auth_token
by authenticating your merchant with the/merchants/authenticate
endpoint. This token will be required to authorize the SoyCap.io API requests. - Campaign Owner’s Keypair: The campaign owner’s
keypair
must be securely loaded and ready to sign the transaction. - Positive
SOL
balance on campaign owner’s wallet.
Process Overview
The process for registering a conversion with SoyCap.io involves the following steps:
- Retrieve Conversion Transaction Details: Use the SoyCap.io API to fetch transaction instructions for registering a conversion. These details are required to create an on-chain transaction.
- Extract Metadata: Parse the metadata returned by the API to retrieve key identifiers, such as the
campaignId
,referralId
, and newly createdconversionId
. - Sign and Send Transaction: Use Solana’s
@solana/web3.js
library to sign and submit the transaction to the blockchain using the campaign owner’s keypair. - Optional: Update Conversion Business Value: For more accurate representation of the campaign performance (ROI), the conversion’s business value (eg. gross revenue) can be updated post-registration.
Step 1: Get Register Conversion Transaction Details
With the auth_token
, request transaction details from SoyCap.io’s /conversions/onchain/create
endpoint. This information is needed to construct the on-chain transaction for conversion registration.
Endpoint: /conversions/onchain/create/:referralId/:publicKey/:amount
referralId
: The ID of the referral associated with the conversion extracted from affiliate attribution.publicKey
: The public key of the merchant’skeypair
.amount
: The reward amount in USDC.
const getRegisterConversionTransactionInstruction = async (referralId, amount, publicKey, token) => { const requestUrl = `${apiUrl}/conversions/onchain/create/${referralId}/${publicKey}/${amount}`;
const response = await fetch(requestUrl, { method: 'GET', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}`, }, });
if (!response.ok) { const errorResponse = await response.json(); throw new Error(`Error: ${errorResponse.error} - ${errorResponse.message}`); }
const data = await response.json(); return data; // Contains transaction instruction and metadata};
// Usageconst referralId = '01JA2SZ20RX8WWGX1360HVPKMD';const amount = 2; // Reward amount in USDCconst transactionData = await getRegisterConversionTransactionInstruction(referralId, amount, publicKey, auth_token);
Step 2. Extract New Conversion Details
The result of the getRegisterConversionTransactionInstruction
function (transactionData
object above) will be returned in the following format:
{ instruction: { keys: [ [Object], [Object], [Object], [Object], [Object] ], programId: '9Tp67R...N4Tstu86snaYw', data: [ 120, 28, 123, 9, 31, 138, 104, 59, 26, 0, 0, 0, 48, 49, 74, 67, 77, 75, 49, 50, 82, 83, 52, 65, 53, 80, 81, 80, 70, 67, 83, 89, 68, 69, 52, 72, 68, 84, 26, 0, 0, 0, 48, 49, 74, 65, 50, 83, 90, 50, 48, 82, 88, 56, 87, 87, 71, 88, 49, 51, 54, 48, 72, 86, 80, 75, 77, 68, 26, 0, 0, 0, 48, 49, 74, 65, 50, 83, 88, 81, 71, 80, 49, 90, 52, 88, 77, 82, 52, 77, 88, 84, 89, 90, 71, 67, 55, 54, 0, 148, ... 6 more items ] }, metadata: { campaignId: '01JA2SXQGP1Z4XMR4MXTYZGC76', referralId: '01JA2SZ20RX8WWGX1360HVPKMD', conversionId: '01JCMK12RS4A5PQPFCSYDE4HDT' }}
You can get the following details from it’s transactionData.metadata
node:
campaignId
- campaign that conversion will be registered for (shall be same as per conversion affiliate attribution)referralId
- referral link that conversion will be registered for (shall be same as per conversion affiliate attribution)conversionId
- new conversion id that shall be created (once transaction is signed and confirmed)
Step 3: Sign and Send the Transaction
Once you have the transaction details, use the Solana @solana/web3.js
library to sign and send the transaction on-chain. The transaction should be signed by the campaign owner’s keypair
. That will create conversion on blockchain and (after some delay) in SoyCap.io offchain DB.
import { Connection, sendAndConfirmTransaction, Transaction, TransactionInstruction } from '@solana/web3.js';
const connection = new Connection(clusterApiUrl('mainnet'), 'confirmed');
const signAndSendTransaction = async (txnInstruction, keypair) => { const { blockhash } = await connection.getLatestBlockhash(); const feePayer = keypair.publicKey;
const instruction = new TransactionInstruction({ keys: txnInstruction.keys.map(key => ({ pubkey: new PublicKey(key.pubkey), isSigner: key.isSigner, isWritable: key.isWritable, })), programId: new PublicKey(txnInstruction.programId), data: Buffer.from(txnInstruction.data) });
const transaction = new Transaction().add(instruction); transaction.feePayer = feePayer; transaction.recentBlockhash = blockhash;
const signature = await sendAndConfirmTransaction(connection, transaction, [keypair]); return signature;};
// Usageconst keypair = loadKeypair(); // Ensure the keypair is securely loadedconst txnSignature = await signAndSendTransaction(transactionData.instruction, keypair);console.log('Transaction successful with signature:', txnSignature);
// Now you can store new conversion details in your DB or update conversion businessValueconsole.log('New conversion details:', transactionData.metadata);
Step 4: Update Conversion Business Value (Optional)
The /conversions/:conversionId/value
API endpoint allows you to update the business value (eg. gross revenue) of a specific conversion. This is particularly useful for campaign ROI calculations, as it ensures that conversions are accurately valued based on real business impact. For instance, if a sale amount is dynamically determined after the initial conversion is logged, this endpoint can be used to update the value, providing a more accurate representation of campaign performance.
const updateConversionBusinessValue = async (conversionId, newValue, token) => { const url = `https://soycap.io/conversions/${conversionId}/value`;
const response = await fetch(url, { method: 'PATCH', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}`, }, body: JSON.stringify({ businessValue: newValue, }), });
if (!response.ok) { const error = await response.json(); throw new Error(`Failed to update conversion value: ${error.message}`); }
const updatedConversion = await response.json(); return updatedConversion; // Returns the updated conversion object};
// Example usage based on transactionData.metadata detailsconst updatedConversion = await updateConversionBusinessValue(transactionData.metadata.conversionId, businessValue, authToken)