Listeners / Delegates for UI / SDK events and Custom User Attributes

This page describes how to implement listeners / delegates for UI / SDK events and Custom User Attributes

To enhance your integration and gain deeper insights into user interactions, implement the following event listeners.

While these steps are not mandatory strictly speaking to make the Purchasely SDK work, we encourage you to implement them as it only takes a few minutes of work.


UI / SDK Events Listener

When users interact with Purchasely Screens, the Purchasely SDK triggers UI / SDK events.

These events are triggered internally inside the application and sent to the Purchasely Platform, to compute all the KPIs related to conversion. However, contrary to Server events, these UI / SDK events cannot be forwarded to a 3rd party integration using a server-to-server integration, directly from the Console.

If you want to leverage these analytics and gain real-time insights on how users interact with the Screens managed by the Purchasely SDK, you need to implement an event delegate / listener, to fetch the events in the app and process them (i.e.: forward them to any analytics or engagement platform)

Implementation

UI / SDK Events are gathered by the Purchasely Platform but they cannot be routed from the Purchasely Console to the webhook or to 3rd party integrations.

If you wish to track these events in your own Analytics or in a 3rd party analytics tool, you need to set yourself an event delegate / event listener inside the app.

Listening to events

 Purchasely.setEventDelegate(self)
Purchasely.eventListener = eventListener
// Nothing special to setup, just go to "Receiving events" below
// Nothing special to setup, just go to "Receiving events" below
// Nothing special to setup, just go to "Receiving events" below
//not available at the moment

This code must be inserted after starting the SDK.

Receiving events

You will receive the events like this :

	func eventTriggered(_ event: PLYEvent, properties: [String : Any]?) {
		switch event {
		case .linkOpened:
			print("Link opened")
		default:
			print("Ignored")
		}
	}
private val eventListener = object : io.purchasely.ext.EventListener {
    override fun onEvent(event: PLYEvent) {
        when (event) {
            PLYEvent.LoginTapped -> Log.d("Purchasely", "Login tapped, we should open login page")
        }
    }
}
Purchasely.addEventListener((event) => {
    console.log('Event Name ' + event.name);
    console.log(event.properties);
    console.log(event);
});

//When you do not want to listen to events anymore
Purchasely.removeEventListener();
Purchasely.listenToEvents((event) =>
  print(event.name)
);
Purchasely.addEventsListener((event) => {
       console.log("Event Name " + event.name);
       console.log(event.properties);
       console.log(event);
});
//not available at the moment

Once received, these events can be directly forwarded to your internal Analytics or 3rd-party Analytics SDK inside your app.


Custom User Attributes Listener

The Purchasely SDK allows you to publish Surveys, gain insights on users and leverage them to personalize the journey.

When a user validates an answer to a survey, a Custom User Attribute can be set by the SDK and fetch by the app thanks to a listener / delegate.

By implementing Custom User Attribute listener, you will be able to:

  1. publish surveys in no-code using the Screen Composer
  2. automatically fetch the user data {attribute, type, value(s)} in the app
  3. and process it to send it to your backend or any 3 party integration

... without needing to update your app every time you publish a new survey.


This feature is available starting from the following versions:

  • iOS: v5.0.2+
  • Android: v5.0.4+
  • React Native: v5.0.4+

Functionning

When the user submit their answer(s) to the Survey, if a user attribute has been associated to the survey, this listener / delegate will automatically be called by the SDK to handover to the app.

After the app has been notified, it can:

  • fetch the data {attribute ID, type, value(s)}
  • and process it

Implementation

class UserAttributeHandler: PLYUserAttributeDelegate {
  func onUserAttributeSet(key: String, type: PLYUserAttributeType, value: Any?, source: PLYUserAttributeSource) {
    print("onUserAttributeSet: \(key) \(type) \(String(describing: value)) \(source)")
  }
  
  func onUserAttributeRemoved(key: String, source: PLYUserAttributeSource) {
    print("onUserAttributeRemoved: \(key) \(source)")
  }
}

Purchasely.setUserAttributeDelegate(UserAttributeHandler())

Purchasely.userAttributeListener = object : UserAttributeListener {
  override fun onUserAttributeSet(key: String, type: PLYUserAttributeType, value: Any, source: PLYUserAttributeSource) {
    Log.d(TAG, "User attribute added: $key, $type, $value from $source")
  }

  override fun onUserAttributeRemoved(key: String, source: PLYUserAttributeSource) {
    Log.d(TAG, "User attribute removed: $key")
  }
}
Purchasely.addUserAttributeSetListener((attribute: PurchaselyUserAttribute) => {
  console.log('Attribute set:', attribute);
});

Purchasely.addUserAttributeRemovedListener(attribute => {
  console.log('Attribute removed:', attribute);
});

// -- Definition of a Purchasely User Attribute -- //
export type PurchaselyUserAttribute = {
  key: string;
  value?: any | null;
  type?: PLYUserAttributeType | null;
  source?: PLYUserAttributeSource | null;
};
class MyUserAttributeListener implements UserAttributeListener {
  @override
  void onUserAttributeSet(String key, PLYUserAttributeType type, dynamic value, PLYUserAttributeSource source){
    print("Attribute set: $key, Type: $type, Value: $value, Source: $source");
  }

  @override
  void onUserAttributeRemoved(String key, PLYUserAttributeSource source) {
    print("Attribute removed: $key, Source: $source");
  }
}

Purchasely.setUserAttributeListener(MyUserAttributeListener());

The listener should be implemented for the following types of Custom User Attributes:

  • String
  • Int
  • Float
  • Bool
  • Date
  • Array of Strings

📘

Surveys allowing multiple choice answers are associated with the type Array of Strings

When configuring your survey, you can define whether multiple answers are allowed or not.

  • If the Survey is configured to allow ONE single answer, the attribute returned will be a String
  • If the Survey is configured to allow MULTIPLE answers, the attribute returned will be an Array of Strings.

Once fetched, the data can be processed, which consist in sending it to your backend or any 3rd party integration directly from the app.

Understanding the PLYUserAttributeSource

The source parameter of the listener/delegate methods indicates where the user attribute update originated. It can have two possible values:

  • PURCHASELY: The change was initiated internally by the Purchasely’s SDK.
  • CLIENT: The change was triggered directly by your app.
@objc public enum PLYUserAttributeSource: Int {
     case purchasely, client
 }
enum class PLYUserAttributeSource {
    PURCHASELY, 
    CLIENT
}
export enum PLYUserAttributeSource {
  PURCHASELY,
  CLIENT
}
enum PLYUserAttributeSource {
  purchasely,
  client,
}

This distinction helps you understand whether the attribute change was driven automatically by Purchasely's SDK or explicitly by your app's logic.

🚧

Ignore the delegate when the parameter source is set to client

When your app sets a Custom User Attribute, the listener / delegate will be called back by the SDK with the parameter source set to client.

To avoid processing a data that you already have - because the app has set it in the first place - in most cases, you can ignore the event triggered when the parameter source is set to client.