# SuperwallDelegate

An interface that handles Superwall lifecycle events and analytics.

> **Note**

Set the delegate using `Superwall.instance.delegate = this` to receive these callbacks. For Java, use `setJavaDelegate()` for better Java interop.



> **Tip**

Use `handleSuperwallEvent(eventInfo)` to track Superwall analytics events in your own analytics platform for a complete view of user behavior.



Purpose [#purpose]

Provides callbacks for Superwall lifecycle events, analytics tracking, and custom paywall interactions.

Signature [#signature]

```kotlin
interface SuperwallDelegate {
    fun subscriptionStatusDidChange(
        from: SubscriptionStatus,
        to: SubscriptionStatus
    ) {}

    fun customerInfoDidChange(
        from: CustomerInfo,
        to: CustomerInfo
    ) {}

    fun userAttributesDidChange(newAttributes: Map<String, Any>) {}
    
    fun handleSuperwallEvent(eventInfo: SuperwallEventInfo) {}
    
    fun handleCustomPaywallAction(name: String) {}
    
    fun willDismissPaywall(paywallInfo: PaywallInfo) {}
    
    fun willPresentPaywall(paywallInfo: PaywallInfo) {}
    
    fun didDismissPaywall(paywallInfo: PaywallInfo) {}
    
    fun didPresentPaywall(paywallInfo: PaywallInfo) {}
    
    fun paywallWillOpenURL(url: String) {}
    
    fun paywallWillOpenDeepLink(url: String) {}
    
    fun handleLog(
        level: LogLevel,
        scope: LogScope,
        message: String,
        info: Map<String, Any>?,
        error: Throwable?
    ) {}
}
```

```java
// Java - Use SuperwallDelegateJava for better Java interop
public interface SuperwallDelegateJava {
    default void subscriptionStatusDidChange(
        SubscriptionStatus from, 
        SubscriptionStatus to
    ) {}

    default void customerInfoDidChange(
        CustomerInfo from,
        CustomerInfo to
    ) {}

    default void userAttributesDidChange(Map<String, Object> newAttributes) {}
    
    default void handleSuperwallEvent(SuperwallEventInfo eventInfo) {}
    
    default void handleCustomPaywallAction(String name) {}
    
    default void willDismissPaywall(PaywallInfo paywallInfo) {}

    default void willPresentPaywall(PaywallInfo paywallInfo) {}

    default void didDismissPaywall(PaywallInfo paywallInfo) {}

    default void didPresentPaywall(PaywallInfo paywallInfo) {}

    default void paywallWillOpenURL(String url) {}

    default void paywallWillOpenDeepLink(String url) {}

    default void handleLog(
        LogLevel level,
        LogScope scope,
        String message,
        Map<String, Object> info,
        Throwable error
    ) {}
}
```

Parameters [#parameters]

All methods are optional to implement. Key methods include:

<TypeTable
  type="{
  subscriptionStatusDidChange: {
    type: &#x22;from: SubscriptionStatus, to: SubscriptionStatus&#x22;,
    description: &#x22;Called when subscription status changes.&#x22;,
    required: true,
  },
  handleSuperwallEvent: {
    type: &#x22;eventInfo: SuperwallEventInfo&#x22;,
    description: &#x22;Called for all internal analytics events. Use for tracking in your own analytics.&#x22;,
    required: true,
  },
  handleCustomPaywallAction: {
    type: &#x22;name: String&#x22;,
    description: &#x22;Called when user taps elements with `data-pw-custom` tags.&#x22;,
    required: true,
  },
  userAttributesDidChange: {
    type: &#x22;newAttributes: Map<String, Any>&#x22;,
    description: &#x22;Called whenever paywall actions mutate user attributes (for example, forms or surveys).&#x22;,
    required: true,
  },
  customerInfoDidChange: {
    type: &#x22;from: CustomerInfo, to: CustomerInfo&#x22;,
    description: &#x22;Raised when Superwall merges device, web, and external purchase data into a new CustomerInfo snapshot.&#x22;,
    required: true,
  },
  willPresentPaywall: {
    type: &#x22;paywallInfo: PaywallInfo&#x22;,
    description: &#x22;Called before paywall presentation.&#x22;,
    required: true,
  },
  didPresentPaywall: {
    type: &#x22;paywallInfo: PaywallInfo&#x22;,
    description: &#x22;Called after paywall presentation.&#x22;,
    required: true,
  },
  willDismissPaywall: {
    type: &#x22;paywallInfo: PaywallInfo&#x22;,
    description: &#x22;Called before paywall dismissal.&#x22;,
    required: true,
  },
  didDismissPaywall: {
    type: &#x22;paywallInfo: PaywallInfo&#x22;,
    description: &#x22;Called after paywall dismissal.&#x22;,
    required: true,
  },
}"
/>

Returns / State [#returns--state]

All delegate methods return `Unit`. They provide information about Superwall events and state changes.

Usage [#usage]

Basic delegate setup:

```kotlin
class MainActivity : AppCompatActivity(), SuperwallDelegate {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Superwall.instance.delegate = this
    }
}
```

Track subscription status changes:

```kotlin
override fun subscriptionStatusDidChange(
    from: SubscriptionStatus,
    to: SubscriptionStatus
) {
    println("Subscription changed from $from to $to")
    updateUI(to)
}
```

Mirror merged purchase history:

```kotlin
override fun customerInfoDidChange(
    from: CustomerInfo,
    to: CustomerInfo
) {
    if (from.activeSubscriptionProductIds != to.activeSubscriptionProductIds) {
        Analytics.track("customer_info_updated", mapOf(
            "old_products" to from.activeSubscriptionProductIds.joinToString(),
            "new_products" to to.activeSubscriptionProductIds.joinToString()
        ))
    }

    refreshEntitlementBadge(to.entitlements.filter { it.isActive }.map { it.id })
}
```

Capture remote attribute changes:

```kotlin
override fun userAttributesDidChange(newAttributes: Map<String, Any>) {
    // Paywall forms or surveys can set attributes directly.
    // Forward them to your analytics platform or local cache.
    analytics.identify(newAttributes)
}
```

Forward analytics events:

```kotlin
override fun handleSuperwallEvent(eventInfo: SuperwallEventInfo) {
    when (val event = eventInfo.event) {
        is SuperwallEvent.PaywallOpen -> {
            Analytics.track("paywall_opened", mapOf(
                "paywall_id" to event.paywallInfo.id,
                "placement" to event.paywallInfo.placement
            ))
        }
        is SuperwallEvent.TransactionComplete -> {
            Analytics.track("subscription_purchased", mapOf(
                "product_id" to event.product.id,
                "paywall_id" to event.paywallInfo.id
            ))
        }
        else -> {
            // Handle other events
        }
    }
}
```

Handle custom paywall actions:

```kotlin
override fun handleCustomPaywallAction(name: String) {
    when (name) {
        "help" -> presentHelpScreen()
        "contact" -> presentContactForm()
        else -> println("Unknown custom action: $name")
    }
}
```

Handle paywall lifecycle:

```kotlin
override fun willPresentPaywall(paywallInfo: PaywallInfo) {
    // Pause video, hide UI, etc.
    pauseBackgroundTasks()
}

override fun didDismissPaywall(paywallInfo: PaywallInfo) {
    // Resume video, show UI, etc.
    resumeBackgroundTasks()
}
```

Java usage:

```java
public class MainActivity extends AppCompatActivity implements SuperwallDelegateJava {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Superwall.getInstance().setJavaDelegate(this);
    }
    
    @Override
    public void subscriptionStatusDidChange(
        SubscriptionStatus from, 
        SubscriptionStatus to
    ) {
        System.out.println("Subscription changed from " + from + " to " + to);
        updateUI(to);
    }

    @Override
    public void customerInfoDidChange(
        CustomerInfo from,
        CustomerInfo to
    ) {
        Logger.i("Superwall", "Customer info updated: " + to.getActiveSubscriptionProductIds());
        syncUserPurchases(to);
    }

    @Override
    public void userAttributesDidChange(Map<String, Object> newAttributes) {
        analytics.identify(newAttributes);
    }
}
```