Radioplayer Developer Reference

Mobile Tracking SDK

Technical reference for Radioplayer partner integrations.

Version
Current
Document type
API / SDK reference
Audience
Radioplayer partner engineering teams

This is the documentation for the Radioplayer Mobile SDK v1.0.0.

General principles

This SDK allows the user to track events which will be collected by the Radioplayer Data Platform.

Annotation-Based Implementation

To keep code maintainable and consistent, the Radioplayer Mobile Data Tracking SDK recommends an annotation-based approach to instrumentation. Instead of inserting trackEvent() calls inside business logic, developers declare tracking intent via annotations , and a separate processing tool injects the required tracking logic.

Benefits

Annotate the callee, not every call site

Place tracking annotations on the method being called (the callee), rather than on each location where it’s invoked.

Why this matters

Installation

  1. Add the downloaded SDK and the following dependencies to the package.json:

    "dependencies": {
    
        // ... existing entries ...
        "@radioplayer/mobile-tracking-sdk": "file:/home/user/.../radioplayer-mobile-tracking-sdk-1.0.0.tgz",
        "@react-native-async-storage/async-storage": "^2.0.0",
        "@react-native-community/netinfo": "^12.0.1",
        "@snowplow/react-native-tracker": "^4.7.0",
        "react-native-geolocation-service": "^5.3.1",
        "react-native-get-random-values": "^1.11.0",
        "react-native-permissions": "^5.5.1",
        "react-native-safe-area-context": "^5.5.2"
    },
    "devDependencies": {
    
        // ... existing entries ...
        "@babel/plugin-transform-class-static-block": "^7.29.7",
        "@babel/plugin-proposal-decorators": "^7.29.0"
    }
  2. Add the following plugins in babel.config.js:

    module.exports = {
        presets: ['module:@react-native/babel-preset'],
    
        plugins: [
    
        // 1. Tracking SDK plugin (must be the first plugin listed here)
        '@radioplayer/mobile-tracking-sdk/plugin',
        '@babel/plugin-transform-class-static-block',
        ['@babel/plugin-proposal-decorators', { version: '2023-11' }],
        ],
    };
  3. Install the SDK:

    npm install

Android

  1. Declare the Geo-Location usage in the android manifest:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
    
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        ...
    
    </manifest>
  2. Start metro:

    npx react-native start --reset-cache
  3. Start the application (tested through adb and a company android phone):

    adb devices
    # List of devices attached
    # R5.......3E	device
    
    npx react-native run-android

iOS

  1. Open ios/Podfile and add the react-native-permissions setup block. It must appear before the target declaration and outside any use_frameworks! block.

    # ... existing Podfile content above ...
    require_relative '../node_modules/react-native-permissions/scripts/setup'
    
    setup_permissions([
      'LocationWhenInUse',
    ])
    
    target 'MyApp' do
      # ... rest of your target block ...
    cd ios && pod install && cd ..
  2. Open ios/MyApp/Info.plist and add the following key inside the root <dict>. If the key already exists with an empty string, update the value.

    <!-- Add inside the root <dict> -->
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>The app requests geolocation access to optimise the listening tracking experience.</string>
  3. Start metro:

    npx react-native start --reset-cache
  4. Start the application (tested on the following iOS simulator versions: 16.4, 18.6, 26.5):

    npx react-native run-ios

Initialization and Configuration

Once you have imported the Radioplayer Mobile Data Tracking SDK files and integrated the code with annotations and related fields, you must explicitly start tracking to begin collecting data from your application. To do this, you need to call the initialize and then the startTracking methods of TrackingSDK object.

To ensure the tracker functions correctly, it must be configured, preferably when your application first starts. The following example demonstrates how to set up the TrackingSDK object.

import { TrackingSDK, ... } from '@radioplayer/mobile-tracking-sdk';

const sdk = TrackingSDK.getInstance();

await sdk.initialize({
        appName: 'my-mobile-sdk',
        appVersion: '1.0.0',
        platformId: platformId, // provided by RP
        productId: productId,   // provided by RP
        deviceInfo: new DeviceInfo('maker', 'model', 'os-name', 14.4, 'my-pseudo-device-id'),
        apiUrl: API_URL,  // provided by RP
        apiKey: API_KEY,  // provided by RP
        debug: false,
    });

await sdk.startTracking(catalogCountryCode);

Please note that once one of these start functions has been called and data collection has begun, you cannot restart it unless stopTracking is called (consecutive calls to start method without calling stopTracking will be ignored).

Default Event Params

Certain information must be associated with each event, regardless of its categorization. Parameters such as the application name (appName), application version (appVersion), platform (platformId) and product (productId) identifiers are defined only once, when the TrackingSDK is initialized, and must remain constant throughout the application execution. These parameters must be defined when initializing the SDK, as they form part of its configuration settings.

The values should be specified in the following manner:

await sdk.initialize({
        appName: 'my-mobile-sdk',
        appVersion: '1.0.0',
        platformId: platformId, // provided by RP
        productId: productId,   // provided by RP
        deviceInfo: new DeviceInfo('maker', 'model', 'os-name', 14.4, 'my-pseudo-device-id'),
        apiUrl: API_URL,  // provided by RP
        apiKey: API_KEY,  // provided by RP
        debug: false,
    });

Other parameters, such as the catalog country code (catalogCountryCode), are passed directly to the new startTracking methods at start-up. The catalogCountryCode can be modified at any time after initialization using updateCatalogCountryCode respectively. Below is an example for each function.

sdk.updateCatalogCountryCode("250")

The string passed to updateCatalogCountryCode function must be a valid_ISO 3166-1_ numeric country code: it must comply with the format of the standard and be associated with an existing nation. If the debug mode is active, the SDK will alert the developer if there are errors with these parameters values.

Debug Mode

To activate the SDK debug mode, you can pass a true flag during initialize or startTracking:

sdk.startTracking("250", true);

In console, in addition to possible warnings about listening session management, each tracked event will also be displayed, along with the collected parameters.

TrackingSDK: All available functions

Initialize the TrackingSDK: initialize()

Initialize tracking of application data.

Parameters

NameTypeDescription
appNameStringThe name of your app/infotainment application. Identifies the app that integrates the SDK
appVersionStringThe version of your app/infotainment application. Version number in format ‘x.x.x’
platformIdStringIdentify the platform where the application is running (provided by Radioplayer)
productIdStringIdentify the specific application into RP products (provided by Radioplayer).
deviceInfoDeviceInfoAn object containing details about the device which the user is connected.
apiUrlStringThe endpoint URL of the data collector. This is where the SDK sends the tracked data
apiKeyStringA unique key for your application, used to authenticate with the tracking service
debugBooleanIndicates whether the instance is in debug mode

Start tracking method : startTracking()

Start tracking of application data.

Parameters

NameTypeDescription
catalogCountryCodeStringThe numeric country code, typically compliant with the ISO 3166-1 standard (see Appendix.A)
debugBooleanA Boolean flag. indicates whether the SDK should be started in debug mode. If true, enables verbose logging for troubleshooting purposes
cmpStateCmpConsentthe CmpConsent to apply at startup; if null, the last persisted consent is loaded from shared preferences

Stop tracking method : stopTracking()

Stops the collection of data generated through the use of the Trackable tags.

Update catalog country code: updateCatalogCountryCode(catalogCountryCode)

Updates the catalog country code stored by the SDK.

Parameters

NameTypeDescription
catalogCountryCodeStringNew ISO 3166-1 numeric country code selected by the user (see Appendix.A)

Updates the consent stored by the SDK.

Parameters

NameTypeDescription
cmpStateCmpConsentthe new CmpConsent to apply

Geo Localization Tracking

The Tracking SDK automatically manages user location tracking based on the Android/iOS permissions grants. The system dynamically adapts to changes in permissions in real time, ensuring privacy compliance and always using the best level of accuracy available.

Event Buffer

The Event Buffer component is designed to collect and optimize events generated by the instrumentation application before they are sent externally.

To ensure efficient data collection, the component locally manages a batch of events by:

Events are held in this local buffer until the batch is full, at which point it is sent. This approach is crucial for preventing data loss. For example, if the device loses its internet connection, the events are safely stored in the local buffer and will be sent automatically as soon as the connection is restored. The optimization of event batching specifically concerns active session management. By aggregating events during an active session, the SDK minimizes the number of transmissions, which in turn optimizes data delivery and reduces overhead.

Tracking Components Usage

In this version of the SDK, the following annotations are available. For correct implementation, you need to import the specific enumerators required from the SDK. This approach makes the code more readable and less prone to errors than using hardcoded strings.

import { SeekStatus } from '@radioplayer/mobile-tracking-sdk';

Every event has mandatory fields , and some also include optional fields.


Notation Supported

All parameters can be declared using either a string literal (e.g., "parameter") or in curly brackets (e.g., "{parameter}"). To populate the optional fields , we recommend using the relativeenumeration to access the supported and recommended values.

The value for optional fields can be defined in two ways:

The second method allows the value to be changed at runtime, as it is dynamically mapped from a variable. When using this approach, keep in mind that the call variable must be of the correct type to ensure data integrity and avoid runtime errors.

Allowed parsing

NOT allowed parsing

The cases not yet supported are:

Class annotation: @Trackable

The @Trackable annotation is used at the class level to identify components whose methods are to be automatically instrumented and tracked by the Device Tracking SDK.

@Trackable({trackableName: 'rs-trackable-name', origin: 'rs-origin', featureOrigin: 'rs-feature-origin'})
class RadioService {
    private freqRadioFav = [88.5, 105.1, 108.0];
    // ...
}

Annotation Element

NameTypeDescriptionMandatory
trackableNameStringIdentifies the trackable sectionMandatory
originStringMandatory
featureOriginStringIndicates the logical feature of the application to which the Trackable belongsMandatory

Method Annotation

The annotations that can be used for methods are listed below.

@RadioStart

This action indicates that a radio stream has started playing. It includes details such as the rpuid and the volume level.

The @RadioStart annotation triggers a listening_session_start event, which signals the _start of a new listening session_. This event allows us to detect when the user starts listening to radio content.

Annotation Element

NameTypeDescriptionMandatory
rpuidStringIt takes the value of RPUID for live contentMandatory
bearerStringRefers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver-
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory
radioModeRadioModeRadio mode used for playbackMandatory
volumeIntVolume level-
outputStringthe output playback deviceMandatory

Example of usage

import { RadioStart, RadioMode } from '@radioplayer/mobile-tracking-sdk';
// ...

@RadioStart({
        rpuid: '{this.radioInfo.rpuid}',
        countryCode: '208',
        radioMode: '{this.radioInfo.mode}',
        bearer: 'fm:9e1.9203.09390',
        output: 'my-output',
    })
startRadio() { ... }

@RadioStop

This action indicates that a radio stream has been stopped. It includes details like the rpuid, bearer and countryCode.

The @RadioStop annotation triggers a listening_session_stop event, which indicates the _end of the listening session_. This allows us to determine when the user has stopped listening to radio content.

Annotation Element

NameTypeDescriptionMandatory
rpuidStringIt takes the value of RPUID for live contentMandatory
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory
radioModeRadioModeRadio mode used for playbackMandatory
volumeIntVolume level-
bearerStringRefers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver-
outputStringthe output playback deviceMandatory

Example of usage

@RadioStop({
        rpuid: '{this.radioInfo.rpuid}',
        countryCode: '{this.radioInfo.countryCode}',
        radioMode: '{this.radioInfo.mode}',
        output: '{this.stereo.mode}',
    })
stopRadio() { ... }

@RadioPause

This action indicates that a radio stream has been paused. It includes details such as the rpuid.

The @RadioPause annotation generates a listening_session_pause event, which signals that the listening session has been paused. In the device domain, in addition to this event, a listening_session_stop event is also generated to indicate that the user has temporarily stopped listening.

Annotation Element

NameTypeDescriptionMandatory
rpuidStringIt takes the value of RPUID for live contentMandatory
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory
bearerStringRefers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver-
outputStringthe output playback deviceMandatory

Example of usage

@RadioPause({
        rpuid: '{this.radioInfo.rpuid}',
        countryCode: '{this.radioInfo.countryCode}',
        output: '{this.stereo.mode}',
    })
pauseRadio() { ... }

@RadioSkip

This action indicates that the radio has skipped to a different station or a different item in a playlist. To populate the skipType field, we recommend to follow the notation supported.

The @RadioSkip annotation triggers a listening_session_skip event, which signals that the user has skipped another radio station. Each skip corresponds to a new listening session, so in addition to the listening_session_skip event, the listening_session_stop and listening_session_start events are also generated.

Annotation Element

NameTypeDescriptionMandatory
newRpuidStringIt takes the value of RPUID for live contentMandatory
newBearerStringRefers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiverMandatory
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory
skipType*SkipStatusIndicates the navigation action performed on the media: previous track, next track, jump to a specific position (JUMP) or reach the end of the content (MEDIA_END)-
outputStringthe output playback deviceMandatory

*Optional: if not provided, defaults to SkipStatus.NEXT.

Example of usage

import { RadioSkip, SkipStatus } from '@radioplayer/mobile-tracking-sdk';
@RadioSkip({
        newRpuid: '276233',
        newBearer: 'dab:1e0.100c.1023.0',
        countryCode: '{this.radioInfo.countryCode}',
        skipType: '{SkipStatus.NEXT}',
        output: '{this.stereo.mode}',
    })
skipRadio() { ... }

@RadioSeek

This action indicates that a user manually changes the playback position of a live radio stream. To populate the seekType field, we recommend to follow the notation supported (see here).

The @RadioSeek annotation triggers a listening_session_seek event, which signals that the audio content is being fast-forwarded or rewound. It is used to understand whether the user is searching for a specific part of the content.

Annotation Element

NameTypeDescriptionMandatory
rpuidStringIt takes the value of RPUID for live contentMandatory
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory
seekType*SeekStatusIndicates whether the seek is backward, forward, or in progress by dragging the bar-
bearerStringRefers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver-
outputStringthe output playback deviceMandatory

*Optional: if not provided, defaults to SeekStatus.FORWARD.

Example of usage

@RadioSeek({
        rpuid: '{this.radioInfo.rpuid}',
        countryCode: '{this.radioInfo.countryCode}',
        seekType: '{SeekStatus.FORWARD}',
        output: '{this.stereo.mode}',
    })
seekRadio() { ... }

@RadioError

This action logs an error when triggered whenever an error occurs during a listening session.

Using the @RadioError annotation triggers a listening_session_error event. This event lets us know when an error related to the listening session has occurred.

Annotation Element

NameTypeDescriptionMandatory
rpuidStringIt takes the value of RPUID for live contentMandatory
bearerStringRefers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver-
reasonStringThe reason for the errorMandatory
outputStringthe output playback deviceMandatory

Example of usage

@RadioError({
        rpuid: '{this.radioInfo.rpuid}',
        reason: 'Weak signal',
        output: '{this.stereo.mode}',
    })
errorRadio() { ... }

@PodcastStart

This action indicates that a podcast episode has started playing. It includes details such as the episode ID (crid) and countryCode.

The @PodcastStart annotation triggers a listening_session_start event, which signals the _start of a new listening session_. This event allows us to detect when the user starts listening to podcast content.

Annotation Element

NameTypeDescriptionMandatory
cridStringIt takes he value of CRID for on-demand contentMandatory
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory
positionIntCurrent time of media in seconds. This value will be equal to the duration value in the case of end of streaming-
outputStringthe output playback deviceMandatory

Example of usage

@PodcastStart({
        crid: '{this.podcastInfo.crid}',
        countryCode: '380',
        position: '{this.currentPosition}',
        output: '{this.stereo.mode}',
    })
startPodcast() { ... }

@PodcastStop

This action indicates that a podcast episode has been stopped. It includes details like the episode ID (crid) and the position at which it was stopped.

The @PodcastStop annotation triggers a listening_session_stop event, which indicates the _end of the listening session_. This allows us to determine when the user has stopped listening to podcast content.

Annotation Element

NameTypeDescriptionMandatory
cridStringIt takes the value of CRID for on-demand contentMandatory
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory
positionIntCurrent time of media in seconds. This value will be equal to the duration value in the case of end of streaming-
outputStringthe output playback deviceMandatory

Example of usage

@PodcastStop({
        crid: '{this.podcastInfo.crid}',
        countryCode: '380',
        position: '{this.currentPosition}',
        output: '{this.stereo.mode}',
    })
stopPodcast() { ... }

@PodcastPause

This action indicates that a podcast episode has been paused. It includes details such as the episode ID (crid) and the position in the episode at which it was paused.

The @PodcastPause annotation generates a listening_session_pause event, which signals that the listening session has been paused. In the device domain, in addition to this event, a listening_session_stop event is also generated to indicate that the user has temporarily stopped listening.

Annotation Element

NameTypeDescriptionMandatory
cridStringIt takes the value of CRID for on-demand contentMandatory
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory
positionIntCurrent time of media in seconds. This value will be equal to the duration value in the case of end of streaming-
outputStringthe output playback deviceMandatory

Example of usage

@PodcastPause({
        crid: '{this.podcastInfo.crid}',
        countryCode: '380',
        position: '{this.currentPosition}',
        output: '{this.stereo.mode}',
    })
pausePodcast() { ... }

@PodcastSkip

This action indicates that the podcast player has skipped to a different episode or a different point within the current episode. It provides details about the current media and the skip type. To populate the skipType field, we recommend to follow the notation supported (see here).

The @PodcastSkip annotation triggers a listening_session_skip event, which signals that the user has skipped another episode of the podcast. Each skip corresponds to a new listening session, so in addition to the listening_session_skip event, the listening_session_stop and listening_session_start events are also generated.

Annotation Element

NameTypeDescriptionMandatory
newCridStringIt takes the value of CRID for on-demand contentMandatory
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory
positionIntCurrent time of media in seconds. This value will be equal to the duration value in the case of end of streaming-
skipType*SkipStatusIndicates the navigation action performed on the media: previous track, next track, jump to a specific position (JUMP) or reach the end of the content (MEDIA_END)-
outputStringthe output playback deviceMandatory

*Optional: if not provided, defaults to SkipStatus.NEXT.

Example of usage

@PodcastSkip({
        newCrid: '61960-4-239200',
        countryCode: '380',
        position: '{this.currentPosition}',
        skipType: '{SkipStatus.NEXT}',
        output: '{this.stereo.mode}',
    })
skipPodcast() { ... }

@PodcastSeek

This action indicates that a user manually changes the playback position of a podcast episode. To populate the seekType field, we recommend to follow the notation supported (see here).

The @PodcastSeek annotation triggers a listening_session_seek event, which signals that the audio content is being fast-forwarded or rewound. It is used to understand whether the user is searching for a specific part of the content.

Annotation Element

NameTypeDescriptionMandatory
cridStringIt takes the value of CRID for on-demand contentMandatory
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory
positionIntCurrent time of media in seconds. This value will be equal to the duration value in the case of end of streaming-
seekType*SeekStatusIndicates whether the seek is backward, forward, or in progress by dragging the bar-
outputStringthe output playback deviceMandatory

*Optional: if not provided, defaults to SeekStatus.FORWARD.

Example of usage

@PodcastSeek({
        crid: '{this.podcastInfo.crid}',
        countryCode: '380',
        position: '{this.currentPosition}',
        seekType: '{SeekStatus.BACKWARD}',
        output: '{this.stereo.mode}',
    })
seekPodcast() { ... }

@PodcastError

This action logs an error when triggered whenever an error occurs during a listening session.

Using the @PodcastError annotation triggers a listening_session_error event. This event lets us know when an error related to the listening session has occurred.

Annotation Element

NameTypeDescriptionMandatory
cridStringIt takes the value of CRID for on-demand content.Mandatory
positionStringRefers to the specific transmission path or mechanism used to deliver the audio content and metadata to a receiver.Mandatory
reasonStringThe reason for the error.Mandatory
outputStringthe output playback deviceMandatory

Example of usage

@PodcastError({
        crid: '{this.podcastInfo.crid}',
        position: '{this.currentPosition}',
        reason: 'Network timeout',
        output: '{this.stereo.mode}',
    })
errorPodcast() { ... }

@ActionFavorite

This action indicates that the user has provided feedback on the currently playing media by marking it as liked or disliked. To populate the like field, we recommend to follow the notation supported (see here).

Using the @ActionFavorite annotation triggers an action event. This event lets us know when the user has performed an action on their favorites (e.g., adding or removing a favorite).

Annotation Element

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
mediaIdStringIt takes the value of RPUID for live content and the value of CRID for on-demand contentMandatory
mediaTypeStringType of the media currently playing (STATION or EPISODE)Mandatory
favoriteOpinionUser feedback on the currently playing mediaMandatory
sourceScreenUiStatusthe output playback deviceMandatory

Example of usage

@ActionFavorite({
        uiSource: 'uiSource-favorite',
        mediaId: '200',
        mediaType: 'STATION',
        favorite: '{Opinion.LIKE}',
        sourceScreen: '{UiStatus.HOME}',
    })
triggerFavoriteAction() { ... }

@ActionPlayback

This action reports the status of media playback, for instance, when a station is buffering or the playback status is updated. To populate the player field, we recommend to follow the notation supported.

Using the @ActionPlayback annotation launches an action event. This event lets us know when the user has interacted with the playback controls.

Annotation Element

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
mediaIdStringIt takes the value of RPUID for live content and the value of CRID for on-demand contentMandatory
mediaTypeStringType of the media currently playing (STATION or EPISODE)Mandatory
player*PlaybackStatusIndicates whether the media is PLAYING, PAUSED, STOP, BUFFERING, REWIND, FORWARD-

*Optional: if not provided, defaults to PlaybackStatus.BUFFERING.

Example of usage

@ActionPlayback({
        uiSource: 'uiSource-playback',
        mediaId: '201',
        mediaType: 'STATION',
        player: '{PlaybackStatus.PLAYING}'
    })
triggerPlaybackAction() { ... }

@ActionRadioMode

This action is used to change the radio band , for example, switching to FM mode. To populate the uiSource field, we recommend to follow the notation supported.

Using the @ActionRadioMode annotation launches an action event. Through this event, we understand when the user has changed or interacted with the radio mode (AM, FM, DAB etc.).

Annotation Element

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
radioMode*RadioModeRadio mode used for playback-

*Optional: if not provided, defaults to RadioMode.DAB.

Example of usage

@ActionRadioMode({uiSource: 'uiSource-radio-mode', radioMode: 'RadioMode.DAB'})
triggerRadioMode() { ... }

@ActionRecClicked

This action indicates that a recommendation was clicked, such as a suggested station or podcast. It captures which recommended item was selected.

Using the @ActionRecClicked annotation, an action event is triggered. This event lets us know when the user has clicked on recommended content.

Annotation Element

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
clickedRecIdStringThe ID of the recommendation that was clickedMandatory
clickedRecTypeStringType of the clicked recommended media (STATION or EPISODE)Mandatory

Example of usage

@ActionRecClicked({
        uiSource: 'uiSource-radio-mode',
        clickedRecId: '202',
        clickedRecType: 'EPISODE'
    })
triggerRecClickedAction() { ... }

@ActionRecClickedSearchResult

This action indicates that a search result item was clicked. It captures which result was selected.

Using the @ActionRecClickedSearchResult annotation, an action event is triggered. This event lets us know when the user has clicked on a search result within the recommendations.

Annotation Element

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the event.Mandatory
clickedMediaIdStringThe ID of the media clicked in the search resultMandatory
clickedMediaTypeStringType of the media currently playing (STATION or EPISODE)Mandatory

*Optional: if not provided, defaults to MediaSource.RADIO_ON_BOARD.

Example of usage

@ActionRecClickedSearchResult({
        uiSource: 'uiSource-rec-clicked-search-result',
        clickedMediaId: '203',
        clickedMediaType: 'EPISODE',
    })
triggerRecClickedSearchResultAction() { ... }

@ActionRecSearch

This action indicates that a search was performed. It records the search query.

Using the @ActionRecSearch annotation launches an action event. This event lets us know when the user has performed a search in the recommendation system.

Annotation Element

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
searchedValueStringThe search value entered by the userMandatory

Example of usage

@ActionRecSearch({
        uiSource: 'uiSource-rec-search',
        searchedValue: 'searched-value',
    })
triggerRecSearchAction() { ... }

@ActionSourceChange

This action indicates that the active radio station has changed and tracks who triggered the change. It distinguishes between an explicit user-initiated change and an automatic/non-explicit change.

Using the @ActionSourceChange annotation, an action event is triggered. Through this event, we understand when the user has changed the playback source (e.g. On-board radio, Mobile Mirroring, Bluetooth, AUX).

Annotation Element

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
mediaSourceMediaSourceSource of the media currently playingMandatory

*Optional: if not provided, defaults to MediaSource.RADIO_ON_BOARD.

Example of usage

@ActionSourceChange({
        uiSource: 'uiSource-source-change',
        mediaSource: 'media-source',
    })
triggerSourceChangeAction() { ... }

@ActionStationChange

This action indicates that the active radio station has changed and tracks who triggered the change. It distinguishes between an explicit user-initiated change and an automatic/non-explicit change.

Using the @ActionStationChange annotation, an action event is triggered. Through this event, we understand when the user has changed radio stations.

Annotation Element

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
mediaIdStringIt takes the value of RPUID for live content and the value of CRID for on-demand contentMandatory
onUserChange*EnablementIndicates whether the user has changed (Enablement.ON) or not (Enablement.OFF) radio station-

*Optional: if not provided, defaults to Enablement.OFF.

Example of usage

@ActionStationChange({
        uiSource: 'uiSource-station-change',
        mediaId: '{this.radioInfo.rpuid}'
    })
triggerStationChangeAction() { ... }

@ActionBroadcast

Annotation Element

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
deviceNameStringName of the deviceMandatory
deviceTypeStringType of the deviceMandatory

Example of usage

@ActionBroadcast({
        uiSource: 'uiSource-broadcast',
        deviceName: 'device-name',
        deviceType: 'phone',
    })
triggerBroadcastAction() { ... }

@ActionDownload

Allows you to track a download and its status.

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
cridStringID of the contentMandatory
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory
stateDownloadStatusStatus of the downloadMandatory

Example of usage

@ActionDownload({
        uiSource: 'uiSource-download',
        crid: '{this.podcastInfo.crid}',
        countryCode: '{this.radioInfo.countryCode}',
        state: '{DownloadStatus.START}',
    })
triggerDownloadAction() { ... }

@ActionFilter

Allows you to track a requested filtering action.

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
filterStringOn which field filtering is appliedMandatory

Example of usage

@ActionFilter({ uiSource: 'uiSource-filter', filter: 'genre' })
triggerFilterAction() { ... }

@ActionShareContent

Allows you to track a requested content sharing.

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
mediaIdStringIt takes the value of RPUID for live content and the value of CRID for on-demand contentMandatory
mediaTypeStringType of the media currently playing (STATION or EPISODE)Mandatory
countryCodeStringCountry code of the played media (ISO 3166 numeric)Mandatory

Example of usage

@ActionShareContent({
        uiSource: 'uiSource-share-content',
        mediaId: '{this.radioInfo.rpuid}',
        mediaType: 'STATION',
        countryCode: '{this.radioInfo.countryCode}',
    })
triggerShareContentAction() { ... }

@ActionTimerSet

Allows you to track the setup of a timer.

NameTypeDescriptionMandatory
uiSourceStringInformation about the UI origin of the eventMandatory
minutesIntegerTemporal amount in minutesMandatory

Example of usage

@ActionTimerSet({ uiSource: 'uiSource-timer-set', minutes: 30, })
triggerTimerSetAction() { ... }

@SetValue

Allows you to track a variable/option change within the application.

Annotation Element

NameTypeDescriptionMandatory
keyStringName of the option changedMandatory
valueStringNew value of the optionMandatory

Example of usage

@SetValue({ key: 'radio_mode', value: '{this.stereo.mode}' })
setModeValue() { ... }

@MetadataUpdate

This action reports an update to the metadata of the currently playing media, such as the artist , song title , and album.

Using the @MetadataUpdate annotation triggers a metadata_update event. This event lets us know when the metadata of the content being played (e.g., song title, artist) has been updated.

Annotation Element

NameTypeDescriptionMandatory
mediaIdStringIt takes the value of RPUID for live content and the value of CRID for on-demand contentMandatory
artistStringName of the artist currently playingMandatory
songStringTitle of the currently playing trackMandatory
albumStringAlbum name of the currently playing trackMandatory
showStringName/title of the program/showMandatory
scheduleStartStringStart time of the show/program schedule windowMandatory
scheduleStopStringEnd time of the show/program scheduleMandatory

Example of usage

@MetadataUpdate({
        mediaId: '{this.radioInfo.rpuid}',
        bearer: '{this.radioInfo.bearer}',
        artist: '{this.currentTrack.artist}',
        song: '{this.currentTrack.song}',
        album: '{this.currentTrack.album}',
        show: '{this.currentTrack.show}',
        scheduleStart: '{this.currentTrack.scheduleStart}',
        scheduleStop: '{this.currentTrack.scheduleStop}',
    })
updateMetadata() { ... }

@ErrorEvent

This action reports a generic unexpected runtime error on the mobile app during normal execution.

Annotation Element

NameTypeDescriptionMandatory
errorTypeCategoryErrorWhich type of error is thisMandatory
sourceStringOrigin of the exceptionMandatory
severitySeveritySeverity level of the exceptionMandatory
reasonStringWhy the exception occurredMandatory
stackTraceStringStack trace of the raised exceptionMandatory

Example of usage

@Error({
        errorType: '{CategoryError.API}',
        source: 'home-screen',
        severity: '{Severity.CRITICAL}',
        reason: '500 response',
        stackTrace: '{this.error.stackTrace}'
    })
error() { ... }

Not all annotations are strictly required from the start. For those approaching the SDK for the first time, it is recommended to focus on the annotations marked with a relevance level of High , as these represent the core integration points for correct and complete functionality.

Annotations with a Medium or Low relevance level can be introduced at a later stage, as the integration matures or based on the specific needs of the product.

AnnotationsRelevance
@RadioStartHigh
@RadioStopHigh
@RadioPauseHigh
@RadioSkipHigh
@RadioSeekHigh
@RadioErrorHigh
@PodcastStartHigh
@PodcastStopHigh
@PodcastPauseHigh
@PodcastSkipHigh
@PodcastSeekHigh
@PodcastErrorHigh
@ActionFavoriteHigh
@ActionPlaybackLow
@ActionRadioModeMedium
@ActionRadioPowerLow
@ActionRecClickedLow
@ActionRecClickedSearchResultLow
@ActionRecSearchLow
@ActionSourceChangeHigh
@ActionStationChangeHigh
@ActionBroadcastLow
@ActionDownloadLow
@ActionFilterLow
@ActionShareContentLow
@ActionTimerSetLow
@SetValueLow
@MetadataUpdateMedium
@ErrorLow

Enumeration

NameValues
CallingStatus["RINGING", "NO_CALL", "ON_CALL"]
CategoryError["GENERAL", "NETWORKING", "PERSISTENCE", "COROUTINE", "MULTITHREADING", "MOBILE_SDK", "DATA_TRACKING_SDK", "METADATA", "API"]
Enablement["ON", "OFF"]
MediaSource["RADIO_ON_BOARD", "MOBILE_MIRRORING", "BLUETOOTH", "AUX"]
Opinion["LIKE", "DISLIKE"]
PlaybackStatus["PLAYING", "PAUSED", "STOP", "BUFFERING", "REWIND", "FORWARD"]
RadioMode["AM", "FM", "DAB", "IP", "HD_RADIO", "DRM", "SIRIUS_XM"]
SeekStatus["BACKWWARD", "FORWARD", "DRAGGING"]
Severity["WARN", "ERROR", "CRITICAL"]
SkipStatus["PREVIOUS", "NEXT", "JUMP", "MEDIA_END"]
SourceStatus["START", "CONTENT"]
UiStatus["HOME", "PODCAST", "LIVE", "RESEARCH", "EASY_MODE", "FOREGROUND", "BACKGROUND"]

Other

Why this class exists

Radioplayer processes different types of data depending on what the user has agreed to. Privacy regulations (ePrivacy Directive, GDPR) require that some of these activities — particularly anonymous usage analytics and precise location retention — only take place when the user has explicitly opted in.

Internally, the SDK maps the consent flags to one of three operating levels defined by CmpState:

Flags grantedResulting CmpStateWhat changes
NoneESSENTIAL_RADIO_SERVICESCore radio functionality only. Location is accessed transiently to find available stations but is never retained
AnalyticsESSENTIAL_SERVICES_USAGE_ANALYTICSAnonymous usage and search statistics are collected to improve the service. Location is still not retained
Analytics + LocationFULL_SERVICE_LOCATION_ANALYTICSLocation data is additionally retained for radio coverage analysis. Requires explicit consent under Art. 5(3) ePrivacy and Art. 6(1)(a) GDPR

Granting location consent automatically implies analytics consent, because location retention is a superset of the analytics processing level. It is not possible to enable location analytics while keeping usage analytics disabled.

Usage

Use the enumeration and the proper method:

import { TrackingSDK, CmpState, } from '@radioplayer/mobile-tracking-sdk';

// ...
sdk.updateConsent(cmpState.FULL_SERVICE_LOCATION_ANALYTICS)

DeviceInfo Class

The DeviceInfo class is a data object for managing device information. The primary goal is to create a unique yet deterministic ID for each device.

Properties:

How the Deterministic ID Works

The ID is automatically generated by the class constructor. This ID is deterministic , meaning that if you use the same parameters (maker, model, osName, osVersion, and pseudoId), the generated ID will always be identical. This feature is useful for identifying the same device across different tracking sessions or applications without relying on an external identifier.

The ID generation process uses a combination of these parameters. Specifically, the maker string, model string, and year, combined with the pseudoId, create a hash that is then converted into a UUID Type 5, ensuring the ID is both immutable and deterministic but at the same time, not invertible.

APPENDIX

A. Country Code

The International Organization for Standardization (ISO) created and maintains the ISO 3166 standard – Codes for the representation of names of countries and their subdivisions. A country code is a standardised identifier that uniquely represents a country (or territory) in computer systems. In this SDK, we exclusively use the ISO 3166-1 numeric standard which defines 3-digit numeric codes (script-independent).

Validation rules

Current ISO 3166 country codes

For an updated list, see: https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes#Current_ISO_3166_country_codes

ISO 3166 country codes (last updated on February 2026)

ISO 3166 nameISO 3166-1 numeric
Afghanistan004
Åland Islands248
Albania008
Algeria012
American Samoa016
Andorra020
Angola024
Anguilla660
Antarctica010
Antigua and Barbuda028
Argentina032
Armenia051
Aruba533
Australia036
Austria040
Azerbaijan031
Bahamas044
Bahrain048
Bangladesh050
Barbados052
Belarus112
Belgium056
Belize084
Benin204
Bermuda060
Bhutan064
Bolivia (Plurinational State of Bolivia)068
Bonaire Sint Eustatius Saba535
Bosnia and Herzegovina070
Botswana072
Bouvet Island074
Brazil076
British Indian Ocean Territory086
British Virgin Islands092
Brunei Darussalam096
Bulgaria100
Burkina Faso854
Burma104
Burundi108
Cabo Verde132
Cambodia116
Cameroon120
Canada124
Cape Verde132
Caribbean Netherlands535
Cayman Islands136
Central African Republic140
Chad148
Chile152
China156
China, The Republic of China158
Christmas Island162
Cocos (Keeling) Islands166
Colombia170
Comoros174
Congo (the Democratic Republic of the Congo)180
Congo178
Cook Islands184
Costa Rica188
Côte d'Ivoire384
Croatia191
Cuba192
Curaçao531
Cyprus196
Czechia203
Democratic People's Republic of Korea408
Democratic Republic of the Congo180
Denmark208
Djibouti262
Dominica212
Dominican Republic214
East Timor626
Ecuador218
Egypt818
El Salvador222
Equatorial Guinea226
Eritrea232
Estonia233
Eswatini748
Ethiopia231
Falkland Islands [Malvinas]238
Faroe Islands234
Fiji242
Finland246
France250
French Guiana254
French Polynesia258
French Southern Territories260
Gabon266
Gambia270
Georgia268
Germany276
Ghana288
Gibraltar292
Great Britain826
Greece300
Greenland304
Grenada308
Guadeloupe312
Guam316
Guatemala320
Guernsey831
Guinea324
Guinea-Bissau624
Guyana328
Haiti332
Heard Island and McDonald Islands334
Holy See336
Honduras340
Hong Kong344
Hungary348
Iceland352
India356
Indonesia360
Iran364
Iraq368
Ireland372
Isle of Man833
Israel376
Italy380
Ivory Coast384
Jamaica388
Jan Mayen744
Japan392
Jersey832
Jordan400
Kazakhstan398
Kenya404
Kiribati296
Korea (the Democratic People's Republic of Korea)408
Korea (the Republic of Korea)410
Kuwait414
Kyrgyzstan417
Lao People's Democratic Republic418
Latvia428
Lebanon422
Lesotho426
Liberia430
Libya434
Liechtenstein438
Lithuania440
Luxembourg442
Macao446
Madagascar450
Malawi454
Malaysia458
Maldives462
Mali466
Malta470
Marshall Islands584
Martinique474
Mauritania478
Mauritius480
Mayotte175
Mexico484
Micronesia (Federated States of Micronesia)583
Moldova (the Republic of Moldova)498
Monaco492
Mongolia496
Montenegro499
Montserrat500
Morocco504
Mozambique508
Myanmar104
Namibia516
Nauru520
Nepal524
Netherlands (Kingdom of the Netherlands)528
New Caledonia540
New Zealand554
Nicaragua558
Niger562
Nigeria566
Niue570
Norfolk Island574
North Korea408
Northern Mariana Islands580
Norway578
North Macedonia807
Oman512
Pakistan586
Palau585
Palestine, State of Palestine275
Panama591
Papua New Guinea598
Paraguay600
People's Republic of China156
Peru604
Philippines608
Pitcairn612
Poland616
Portugal620
Puerto Rico630
Qatar634
Republic of China158
Republic of Korea410
Republic of the Congo178
Réunion638
Romania642
Russian Federation643
Rwanda646
Saba535
Sahrawi Arab Democratic Republic732
Saint Barthélemy652
Saint Kitts and Nevis659
Saint Lucia662
Saint Martin (French part)663
Saint Pierre and Miquelon666
Saint Vincent and the Grenadines670
Saint Helena Ascension Island Tristan da Cunha654
Samoa882
San Marino674
Sao Tome and Principe678
Saudi Arabia682
Senegal686
Serbia688
Seychelles690
Sierra Leone694
Singapore702
Sint Eustatius535
Sint Maarten (Dutch part)534
Slovakia703
Slovenia705
Solomon Islands090
Somalia706
South Africa710
South Georgia and the South Sandwich Islands239
South Korea410
South Sudan728
Spain724
Sri Lanka144
Sudan729
Suriname740
Svalbard Jan Mayen744
Sweden752
Switzerland756
Syrian Arab Republic760
Taiwan (Province of China)158
Tajikistan762
Tanzania, the United Republic of Tanzania834
Thailand764
Timor-Leste626
Togo768
Tokelau772
Tonga776
Trinidad and Tobago780
Tunisia788
Türkiye792
Turkmenistan795
Turks and Caicos Islands796
Tuvalu798
Uganda800
Ukraine804
United Arab Emirates784
United Kingdom of Great Britain and Northern Ireland826
United States Minor Outlying Islands581
United States of America840
United States Virgin Islands850
Uruguay858
Uzbekistan860
Vanuatu548
Vatican City336
Venezuela (Bolivarian Republic of Venezuela)862
Viet Nam704
Virgin Islands (British)092
Virgin Islands (U.S.)850
Wallis and Futuna876
Western Sahara732
Yemen887
Zambia894
Zimbabwe716

B. Country Code vs Catalog Country Code

CountryCode

Indicates the country associated with the media currently being played (e.g., selected radio station, selected podcast/stream). Therefore, it changes based on the content being played.

CatalogCountryCode

Indicates the country of the content catalog used by the app for browsing/searching/listing. This value is chosen when the app is initialized and remains stable until it is reinitialized/changed.

Why they may be different

A user may want to listen to content from the Italian catalog (CatalogCountryCode = IT), but be located in Germany (CountryCode = DE).

In this case, an FM/DAB scan based on the receiver will mainly find German stations, because it depends on local coverage and the region where the device is located.

Practical example

_CatalogCountryCode_ = IT → the user is browsing/filtering “Italy” content (Italian stations, metadata, IT market lineup).

_CountryCode_ = DE → the tuner scan/search returns frequencies/stations that can be received in Germany.

C. WRAPI

The Radioplayer Partner API (WRAPI) provides developers with unparalleled access to broadcasters' streaming radio programming and proprietary metadata. You can use this to build a rich and flexible hybrid radio experience for your customers.

The base address for the Radioplayer Partner API (WRAPI) is: api.radioplayer.org/v2/

There are ten endpoints to the Radioplayer Partner API (WRAPI):

WRAPI endpoints

EndpointPurpose
_/stations_returns a list of all information on all stations, unless filtered by parameters. Also provides the ability to search for stations in a number of ways including keyword searching, category searching, search by bearers and search for local station.
_/stations/{rpuids}_returns information on a particular station, identified by its rpuid.
_/stations/{rpuids}/onair_provides current “track now playing” information from one or multiple radio stations.
_/stations/{rpuids}/schedule_returns programme schedules for up to five radio stations.
_/stations/{rpuid}/ondemand_returns a list of on-demand items for a given radio station.
_/stations/{rpuid}/ondemand/{seriesId}_returns a list of on-demand content for a given series.
_/ondemand_returns details on all pieces of on-demand content, unless filtered by parameters which include text searching, filtering by category, country or station.
_/ondemand/{odIds}_returns all information on a particular piece of on-demand content, identified by its OD ID.
_/recommendations_shows recommended content based on station affinity, music preferences from social media such as facebook, geolocation and generally trending stations.
_/categories_returns a list of categories for live and on demand content which can be used when searching for content by category.

For complete documentation, see Radioplayer Partner API (WRAPI) documentation.

D. RadioConnectApi

TBD

E. RPUID

TBD

F. Category Error

Below is an explanation of the values in the CategoryError enumeration.

ValueDescription
GENERALGeneric error not attributable to a specific domain
NETWORKINGError related to network connectivity or HTTP communication
PERSISTENCEError related to local data persistence (database, file I/O)
COROUTINEError originating from a coroutine or asynchronous operation
MULTITHREADINGError caused by multithreading or concurrency issues
MOBILE_SDKError internal to the mobile SDK
DATA_TRACKING_SDKError internal to the Data Tracking SDK
METADATAError related to metadata retrieval or parsing
APIError returned by or related to an external API call

G. Radio Mode

Below is an explanation of the values in the RadioMode enumeration.

ValueDescription
AMAmplitude Modulation broadcast (Medium Wave / Long Wave)
FMFrequency Modulation broadcast
DABDigital Audio Broadcasting (DAB, also known as DAB classic)
IPInternet-delivered radio stream (IP-based)
HD_RADIOA digital radio system used primarily in the United States, allowing digital broadcasts alongside existing AM/FM frequencies.
DRMA digital radio standard designed for AM and shortwave bands (and sometimes FM).
SIRIUS_XMSubscription-based satellite radio service available mainly in the United States and Canada.