Docs
grovs.io Start for free

Revenue

Track store purchases, Unity IAP purchases and custom payments with the Grovs Unity SDK.

Log purchases to attribute revenue to links and campaigns, and see ARPU, LTV and product and platform breakdowns in the dashboard. Revenue tracking is in beta.

Self-hosted: revenue tracking needs the Enterprise edition (GROVS_EE=true). A Community edition backend has no purchase endpoint.

Setup

1. Enable revenue tracking in the dashboard

  1. In the Grovs dashboard, go to Analytics → Revenue.
  2. Click Enable Revenue Tracking. Only instance admins can turn it on or off.

See Revenue for the dashboard and Goals for revenue goals.

2. Configure platform notifications

Unity IAP

When com.unity.purchasing 4.0 or newer is in the project, the GrovsSDK.IAP assembly compiles and adds GrovsUnityIAP. It reads the Unity IAP receipt and supports the Apple App Store, the Mac App Store and Google Play.

IAP 4, or the IAP 5 Product path:

C#
using GrovsSDK;
using UnityEngine.Purchasing;
 
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
    _ = GrovsUnityIAP.LogPurchaseAsync(args.purchasedProduct);
    return PurchaseProcessingResult.Complete;
}

IAP 5 Order path (needs com.unity.purchasing 5.0 or newer):

C#
void OnPurchasePending(PendingOrder order)
{
    // Log before confirming: on iOS the receipt can be null afterwards.
    _ = GrovsUnityIAP.LogOrderAsync(order);
    storeController.ConfirmPurchase(order);
}
  • On IAP 5 on iOS, log before you confirm a consumable. After confirming, the receipt can be null.
  • A null product or order throws ArgumentNullException.
  • The task resolves false, with a [Grovs] Purchase not logged. warning, when the receipt can't be used: invalid JSON, no transaction ID, or another store.

Store purchases without Unity IAP

Pass the platform's transaction yourself:

C#
#if UNITY_IOS
// The StoreKit transaction ID, as a decimal string
bool logged = await Grovs.LogInAppPurchaseAsync(transactionId);
#elif UNITY_ANDROID
// The Play Billing purchase's originalJson
bool logged = await Grovs.LogInAppPurchaseAsync(purchase.originalJson);
#endif
  • An empty or null string throws ArgumentException.
  • iOS: the string must be a decimal number, or the task fails with InvalidArgument. The result is the native SDK's result.
  • Android: the result is true once the purchase is handed to the native SDK.

The backend then looks the transaction up, fills in product, price and currency, and de-duplicates repeated calls.

Custom purchases

For payments outside the stores:

C#
bool logged = await Grovs.LogCustomPurchaseAsync(GrovsTransactionType.Buy, 199, "USD", "coins_100");
ParameterTypeDescription
typeGrovsTransactionTypeBuy, Cancel or Refund
priceInCentsintAmount in cents, for example 199 for $1.99
currencystringISO 4217 code, for example "USD"
productIdstringYour product identifier
dateDateTime?Transaction date. null (the default) means now.

A null currency or product ID throws ArgumentNullException. On Android the result is true once the purchase is handed to the native SDK.

Log a cancellation or refund with the same call and GrovsTransactionType.Cancel or GrovsTransactionType.Refund. App Store and Google Play cancellations and refunds are detected through the platform server notifications.

Errors

Purchase tasks fail with GrovsException when Grovs is disabled (SdkDisabled) or not started (SdkNotInitialized). In the Editor and on other platforms they resolve false.

Last updated 2026-10-26
Was this page helpful?