RadiumOne FAQs | Comparably
RadiumOne builds software that automates media buying, making big data actionable for digital marketers. read more
EMPLOYEE
PARTICIPANTS
3
TOTAL
RATINGS
74

RadiumOne FAQs

RadiumOne's Frequently Asked Questions page is a central hub where its customers can always go to with their most common questions. These are the 34 most popular questions RadiumOne receives.

Frequently Asked Questions About RadiumOne

  • Within Mobile Analytics everything comes down to tracking events.

    Each event in turn has a set of attributes that add dimensions and depth and which we can use to analyze them after the fact.

    Some clients will have very strong ideas of what events they should be tracking and what attributes are important for each. Others will require more hand holding.

    Anything that happens in the app code can be tracked as an event, not just user actions. So, for example, in a dating app a user might tap 'Like" on another users profile and that's obviously trackable as an action, but when the system recognizes that both users have clicked "Like" and sends them both notifications, sending the "Like" notification can also be tracked as an action.

    If you are unsure, please bring in a Solution Engineer who can talk through the use cases with them.

    Set of available events includes:

    1) Automatic Events

    The R1 Mobile Analytics SDK will automatically capture some generic events in order to get the most meaningful data on how users interact with your application. These events are triggered when the state of the application is changed, and therefore do not require any additional code to work out of the box:

    Launch- emitted when the app starts

    First Launch- emitted when the app starts for the first time

    First Launch After Update- emitted when the app starts for the first time after a version upgrade

    Application Opened- emitted when your app is opened after a message is sent.

    Session Start- emitted when a new session starts

    Session End- emitted when a session ends; includes a Session Length attribute with the session length in seconds

    2) Standard Events

    Standard Events cover all the main user flows (login, register, share, purchase...) in a standardized format for optimized reporting on the portal, providing a great foundation for your analytics strategy. They unlock great insights, particularly with respect to user lifetime value.

    Login -Tracks a user login within the app

    Registration -Records a user registration within the app

    Facebook connect -Allows access to Facebook services

    Twitter connect -Allows access to Twitter services

    User Info -This event enables you to send user profiles to the backend.

    Upgrade -Tracks an application version upgrade

    Trial Upgrade -Tracks an application upgrade from a trial version to a full version

    Screen View -Basically, a page view, it provides info about that screen

    Transaction -A purchase

    TransactionItem -Deprecated, use the Transaction event instead.

    Delete Cart

    Add To Cart

    Delete From Cart

    3)Custom Events

    Custom events enable you to create and track specific events that are more closely aligned with your app. If planned and structured correctly, custom events can be strong indicators of user intent and behavior. Some examples include pressing the like button, playing a song, changing the screen mode from portrait to landscape, and zooming in or out of an image. These are all actions by the user that could be tracked with events.

    Custom events can also be used to track things that happen in an app that do not involve direct user input. For instance a dating app could fire an event when the server matches two users based on interest and it sends them both notifications, even though neither end user has taken an action yet.

    4) In-App Webview Events

    By setting up in-app webview events, you can track events that begin inside your native application but are completed in the embedded browser. To do so, you will have to embed some JavaScript in the page that you will want to fire the event, and you need to properly trigger the webview in your application. These can include events in any of the three categories above.

    Read More:

    Implement event tracking in iOS Implement event tracking in Android

    View Article
  • This guide is intended to summarize the available integration options so that you can easily plan your deployment.

    The first thing to do is Sign up for a free account( http://connect.radiumone.com/register/ ). Note that each account is tied to a single email address at this time so you'll need to share access between your engineers who will build the integration and the people usingthe reporting. After integration is complete you can change the password on the account if desired.

    Once you have your account, the integration steps are as follows:

    Steps:

    Plan your Integration

    Identify events to measure your Key Performance indicators (KPI's)

    Identify user groups you want to target with push notifications

    Select an integration option

    Software Development Kit (SDK)

    API Integration from your app

    Server to Server Integration via API

    API integration from a third party tool

    Testing and QA

    Submit app

    1. Plan your Integration:

    Identify key events

    RadiumOne Mobile Analytics is fundamentally based on tracking Events - things that happen in your app. Those things can be user actions like tapping a button or completing a purchase, or they can be something that happens on the app side such as one user being matched to another in a dating app.

    RadiumOne Mobile Analytics will automatically track:

    Launch - fired when the app starts

    First Launch - fired when the app starts for the first time

    First Launch After Update -fired when the app starts for the first time after a version upgrade

    Application Opened - fired when your app is opened after a message is sent.

    Session Start - fired when a new session starts

    Session End - fired when a session ends; includes a Session Length attribute with the session length in seconds

    What else should I track?

    You can track any number of custom events in Mobile Analytics, but rather than just tracking everything and cluttering your dashboard with irrelevant data, we recommend stopping to consider what the Key Performance Indicators (KPI's) are for your app. These will vary considerably depending on your vertical and your particular approach and there is no one-size-fits-all solution.

    To make it easier, we have standardized data formatting for a few very common events, these include:

    Login: Tracks a user login within the app

    Registration: Records a user registration within the app

    Facebook connect: Track this when the user allows access to Facebook services

    Twitter connect: Track this when the user allows access to Twitter services

    User Info: This event enables you to send user profiles to the backend. Please do not send us personally identifiable information!

    Upgrade: Tracks an application version upgrade

    Trial Upgrade: Tracks an application upgrade from a trial version to a full version

    Screen View: Basically, a page view, it provides info about that screen

    Transaction: A purchase

    Delete Cart

    Add To Cart

    Delete From Cart

    You are not limited to these predefined events, however, and can add your own custom events as well.

    Key things to consider about what to track:

    What are the critical parts of the user experience in my app?

    Where am I losing users? What features need improvement?

    Does my user base spending a lot of time with one feature mean it is broken and a time suck for users or does it mean they love it and are very engaged? How can I tell the difference?

    What will I learn by tracking this event?

    How is it relevant to my KPI's?

    What attributes of the event are important? For example, a Transaction event should at minimum include the value of the transaction and the names or ID's of the item or items purchased, but depending on your monetization model might benefit from other contextual info as well.

    To get the best results, we recommend having all your stakeholders sit down and discuss what they want to know and whats important to them. Unlike many analytics solutions, we do not have a cap on the number of trackable events so you can be as comprehensive as you want.

    If you are new to Analytics and need a hand figuring this out, please reach out to our support team and we will be happy to help make sure you get the data you need and are able to implement tracking quickly and easily.

    2. Integration Options

    SDK Installation

    This is by far the most common route and the easiest for us to support and debug. Unlike some other tools, the RadiumOne Mobile Analytics SDK plays no role in the day to day functioning of your app - its not serving ads or in-app content - and is purely a reporting tool. That keeps the footprint incredibly lightweight and implementation simple. Key functionality includes offline queing of messages to our endpoint so youdon'tlose data when users go offline.

    Basic SDK integration can be accomplished in a few hours. Beyond that, the time requirements are totally dependent on the tagging and event tracking you want to put in place.

    The basic steps are outlined here: https://support.radiumone.com/hc/en-us/articles/218279063

    For full step by step instructions, please refer to our documentation on Github.iOS: https://github.com/radiumone/r1-connect-demo-iOS

    Android: https://github.com/radiumone/r1-connect-demo-Android

    Windows: https://github.com/radiumone/r1-connect-demo-WP/tree/master/R1ConnectDemo

    Phonegap: https://github.com/radiumone/r1-connect-demo-phonegap

    Titanium: https://github.com/radiumone/r1-connect-titanium

    API Integrations

    In all of these scenarios, integration is accomplished by sending push notifications to the RadiumOne Mobile Analytics Event Tracker API.

    Youll need to go through the normal setup steps, the same as if you were integrating the RadiumOne Mobile Analytics SDK.

    Register App with RadiumOne Mobile Analytics and retrieve the application id from the RadiumOne Mobile Analytics Dashboard.

    Set up your system to push event data to RadiumOne Mobile Analytics. This must include:

    First launch of app for each end user as it occurs

    Session data for end users

    Any Event data that you wish to track and segment upon

    Messages must follow the rules and structure laid out in the RadiumOne Mobile Analytics API doc: https://support.radiumone.com/hc/en-us/articles/207516263-RadiumOne-Mobile-Analytics-Event-Tracker-Endpoint-API-

    There are three main flavors of API integration:

    API Integration from the app

    Many companies are wary of SDK implementations because theydon'twant to put someone elses software into their app. If that sounds like you, building your own integration that makes the same calls to our endpoint that would be made by our SDK can be an effective route to integration. Doing so is more work than integrating the SDK but gives your developers complete control over what data is sent and under what circumstances. It is essentially a 1 for 1 replacement of the SDK. Because of the extra work required, this is not recommended unless SDK integration is completely off the table and you lack the server infrastructure required for other API integrations.

    This is an ideal solution in cases where:

    You do not want to integrate an SDK

    Your team has the technical expertise to manually handle message queing and other functionality normally handled by our SDK

    You are not collecting useage data either on your own servers or via a third party OR you are collecting the data but do not have a way to dynamically send it to the RadiumOne Mobile Analytics API OR you want to avoid the cost of relaying messages through your own servers.

    Server to Server API integration from your internal server

    Perhaps you are already be collecting useage data for all the events you want to track in on your own servers and want to pass that data on to RadiumOne Mobile Analytics from that server for analysis and action. In this scenario, you simply fire messages to the RadiumOne Mobile Analytics endpoint for that useage data as it comes into your servers like a relay race.

    This is an ideal solution in cases where:

    You cannot integrate an SDK

    You already have your own in-house data infrastructure set up that is already receiving data from end users about what they are doing.

    Those servers are capable of pushing notifications about end user behavior to MAs API endpoints in real time.

    Server to Server API integration from third party tool

    This scenario is best for cases where you want to use the RadiumOne Mobile Analytics dashboard and functionality in addition to some other previously implemented external tool.

    Available options here are:

    Appsflyer

    Kochava

    TUNE

    Segment

    mParticle

    Tealium Mobile

    3. Testing and QA

    RadiumOne Mobile Analyticsis a complex product with lots of moving parts. Depending which modules you are using, you may be able to omit some of these steps.

    Testing Process

    If you will be doing mediaattribution through Mobile Analytics, request tracking links or access for your test build from your RadiumOne account manager. Click the link on your test device.

    Open the test build of your app

    Perform each of the tracked actions at least once.

    Wait half an hour and check reports to make sure all events have been recorded along with relevant attributes. We recommend using the Trends report to check that all the events have come through and the Segmentation report to easily check attributes.

    If applicable, check to make sure the Track dashboard has successfully attributed your test installs.

    4. App submission

    For iOS you will need to check the box declaring that you are collecting IDFA in order to attribute ads displayed elsewhere. Full steps and detailed instructions are at https://support.radiumone.com/hc/en-us/articles/207311053-iOS-SDK-App-Submission

    For Android there are no special submission requirements.

    View Article
  • One of the areas in which Mobile Analytics is highly differentiated from other mobile analytics solutions is in its ability to leverage user behavior data to boost efficiency and ROI for your programmatic media campaigns.

    At this time, custom audiences can be created from the Segmentation, Funnels, and Retention reports.

    Please either contact your Account Manager or [email protected] to make sure your Mobile Analytics account is tied to your RadiumOne advertising account before starting this process.

    Creating audiences from Segmentation report

    Click the "New Segmentation" button on the Segmentation report to launch the configuration wizard or the "edit" link to leverage an existing segment. Note that once a report is tied to an Audience it can no longer be edited.

    Name your segment using the text box at the top right.

    Select the date range for your segment.

    Select an operating system filter to target users on a single platform (iOS, Android, Windows) or leave the filter blank to include all users.

    Select the event that will define the segment and any attributes. For example, on a Transaction event it would be common to select carrier_country, the item name, or the price. If you have demographic information in your attributes it might be useful as well. Depending on your industry and your app, the options selected can vary considerably. To ensure you have the data you will need here, we recommend consulting with our Solutions Engineering team ahead of implementation to make sure your bases are covered.

    Pay careful attention to attributes since that is where all your context is found. The available data includes all of the automatically tracked event attributes, plus any custom attributes you may have added. This lets you narrow the focus of your audience for more precise targeting. For attributes that have multiple possible values, you can determine how many of those values to include by checking the appropriate boxes.

    Once you have your Audience defined, click the button "+ Create Audience for Ad campaign" to push the audience to the RadiumOne DMP

    Note that the Segmentation report has three main view types - Users (the set of users in your segment), Events (the number of times the event that the segment is built on happened), and Events per User (the number of times per end user that the segmenting event occurred). Changing this will change the data visualization shown in the dashboard because it shows a different part of the data set, but does not impact the Audience being defined.

    Screenshot of Segment creation. Hit "Create Audience for Ad campaign" to make segment targetable.

    Creating audiences from Funnels

    Funnels are a classic form of user flow analysis and allow you to map out common user experiences and identify dropoff points. This report will show you what percent of the users who completed a particular action went on to complete some other specific action, out of the set that completed both how many completed a third, and so on. You can also segment each step of the funnel for more focused analysis

    Creating Audiences from Funnels is powerful because it allows you to:

    Run re-engagement campaigns aimed at users who have dropped off in order to bring them back in.Example: Use the Exclusion option to target users who have not completed the last step of your funnel with a deep-linked ad that takes them directly to the appropriate content.

    Run retention campaigns against users who are engaged in order to build useage habits around your app.Example: Use the Inclusion option to target users who have completed the last step of your funnel and encourage them to take some other high-value action in your app. This helps reinforce useage habits and keeps those high-value users engaged.

    Use lookalike targeting to acquire new users similar to the ones who have completed your funnel and proven their valueExample: Use the Inclusion option to identify high-value users (for instance, users who got all the way through your tutorial and made at least one purchase) so we can find users who share similar interests and useage patterns to target as part of your growth campaign.

    How to:

    Click the "New Funnel" button on the Funnels report to launch the configuration wizard or the "edit" link to update an existing Funnel. Note that once a report is tied to an Audience it can no longer be edited.

    Name your Funnel using the text box at the top right

    Select the date range for your Funnel.

    Select an operating system filter to target users on a single platform (iOS, Android, Windows) or leave the filter blank to include all users.

    Select at least two events and any attributes. You can add additional steps using the "+ Add Step" button at the bottom of the configuration screen.

    Pay careful attention to attributes since that is where all your context is found. The available data includes all of the automatically tracked event attributes, plus any custom attributes you may have added. This lets you narrow the focus of your audience for more precise targetting. For attributes that have multiple possible values, you can check how many of those values to include.

    Re-order the steps as needed using the Re-order buttons.

    Once your funnel is complete, click "Create Funnel"

    Once created, you can create and audience from a Funnel by clicking the "Create Audience for Ad-campaign" button at the bottom of the report.

    Doing so reveals the audience creation tools which let you select a Campaign period and a Segment type that lets you choose either Inclusion or Exclusion to target or exclude users who completed the last step of the funnel. The end date for the campaign can be in the future.

    Once created you can view these audiences but cannot alter them

    Creating a Funnel: Setting up the steps, look back, platform, and segmentation.

    Creating a Funnel: View of funnel, click "Create Audience for Ad-campaign" button to create a targetable audience.

    Creating a Funnel: Select Campaign period and set Exclusion or Inclusion targeting.*

    *Note that the set of users is defined by the lookback window, not just the start and end dates. So if my window is Feb 1 to Feb 8 and I have a 7 day look-back, my data set for day 1 includes everyone who completed the Funnel from January 25th to February 1st. Day two would be January 26th to February 2nd, and so on..

    Creating audiences from Retention

    The Retention tool is a powerful Cohorting tool that lets you view how many users who completed one event went on to complete a second event on each of the days following. That can include classic retention metrics like First Launch vs Session (to show how many new users who started on a given day opened the app on each of the following days) or more custom metrics that are specific to your app.

    Creating Audiences from retention reports is powerful because it allows you to:

    Run re-engagement campaigns aimed at users who have dropped off in order to bring them back in.Example: Use the Exclusion option to target users who have not completed the retention event with a deep-linked ad that takes them directly to the appropriate content.

    Run retention campaigns against users who are engaged in order to build usage habits around your app.Example: Use the Inclusion option to target users who have completed your retention event and encourage them to do it again or take some other high-value action in your app. This helps reinforce useage habits and keeps those high-value users engaged.

    Use lookalike targeting to acquire new users similar to the ones who meet your retention criteria.Example: Use the Inclusion option to identify high-value users (for instance, users who have made two purchases in a seven day period) so we can find users who share similar interests and useage patterns to target as part of your growth campaign.

    How to:

    Click the "New Retention" button on the Retention report to launch the configuration wizard or the "edit" link to leverage an existing Retention report. Note that once a report is tied to an Audience it can no longer be edited.

    Name your Retention using the text box at the top right

    Select the date range for your report.

    Select an operating system filter to target users on a single platform (iOS, Android, Windows) or leave the filter blank to include all users.

    Select the Population Event - the event that creates the initial set of users to analyze.

    Select the Retention event - the event that will be used as your success metric.

    Once you have your Audience defined, click the button "Create Audience for Ad campaign" to expand the Audience creation section of the page.

    Select the Campaign period - the period of time during which you want users who meet your criteria to be added to this audience. The end date can be in the future.

    Select the Lookback window. Your Lookback window is the number of days before the campaign start date that would be considered for the audience creation. This window will be incremented daily.

    Select either Inclusion (to add people who have been retained to the audience) or Exclusion (to add people who have not completed the retention event during the window).

    Select Single day (only users who qualified/disqualified on the last day) or Cumulative (all users who meet your criteria durign the lookback window) for Grouping.

    Double check your selections and then hit button marked "Create Retention with Audience for Ad-campaign" to save the audience.

    Retention: Pick events, platform, and date range.

    Retention: Select duration of campaign, look back period, targeting, and grouping and then hit "Create Retention with Audience for Ad campaign.

    Viewing your saved audiences

    Saved audiences from all three reports can be accessed from the left navigation bar in the "Analyze" section of Mobile Analytics by clicking "View DMP Audiences". Doing so brings up a searchable list of all created audiences, along with the source report, audience ID, date created, and the appropriate details.

    View Article
  • Introduction

    RadiumOne currently has two mechanisms in order to track in-App mobile data and allow segmentation of that data into our DMP:

    RadiumOne RadiumOne Mobile Analytics SDK ( iOS, Android )

    RadiumOne Event Tracker EndPoint

    If for some reason youcannot usethe RadiumOne RadiumOne Mobile Analytics SDK, this Endpoint provides an alternative path to integrate either directly from your app or server to server.

    This endpoint accepts data that is formatted in a JSON format with well-defined parameters.

    Registering your application in RadiumOne RadiumOne Mobile Analytics

    In order to be able to track your application and make use of it, you need to register it in RadiumOne RadiumOne Mobile Analytics. It is easy to do.

    You access RadiumOne RadiumOne Mobile Analytics here: connect.radiumone.com

    Once you are registered, you can create a new app through the RadiumOne Mobile Analytics process. Then you can access the information that you will need from the settings view.

    You will want to retrieve the application id field, as it is necessary for data to be processed. The format of the application id is a GUID and it will look like this: 8E19B036-3848-4AB7-A21A-536B70A5C0A6

    Please note that the previous value is an example.

    Endpoint information

    In order to pass information to RadiumOne, you need to use the following endpoint:

    Staging: https://rp-stg.gwallet.com/r1t/evt3/#{application_id}?v=2

    Production: https://rp.gwallet.com/r1t/evt3/#{application_id}?v=2

    {application_id} is the value that RadiumOne RadiumOne Mobile Analytics has assigned to you through the UI. All calls should be made to this dynamic endpoint. This will allow the data to flow into the system.

    All data should be passed as POST and should be sent as HTTPS.

    Responses

    If the data passed via the POST query is correct, you will receive a 200 response with the message Well done or else you will see Bad Request

    Event details

    The system has several events that are defined by default. Any system put in place should replicate these events.

    Here are the automatic events that the SDK supports:

    Launch- emitted when the app starts

    First Launch- emitted when the app starts for the first time

    First Launch After Update- emitted when the app starts for the first time after a version upgrade

    Application Opened- This event is very useful for push notifications and can measure when your app is opened after a message is sent.

    Similarly, it is possible to create your own events based on the event data structure.

    Each of these events will be detailed in Appendix A to explain how they should actually be filled.

    Pre-conditions and System setup

    Before you send any data, please ensure the following,

    Utilize persistent HTTPS connections

    Limit 1,000 QPS or 250 Mbps per connection

    Combine multiple events from a given device into a single HTTPS POST message (up to 1MB in size)

    The endpoint can support in the range of 50,000 QPS

    Currently we do not support event de-duplication on the logger side, so it depends on how duplicate events are handled on the data processing side.

    Rules for posting data

    App UUID must be valid and the app must be active

    source field is required

    event_info - at least one event must be present

    event_info.event_name must be non-empty

    device_info.id_info - at least one device ID must be present

    event_info.transaction_id is required

    event_info.timestamp is required

    event_info.key_value.key is required (if event_info.key_value is present)

    RadiumOne Mobile Analytics Key Name

    Type

    Sample Value

    Default behavior

    Description

    Mandatory

    application_id

    String

    application_name (bundle_name)

    If (null) ERROR

    Combination of application name and bundle name

    Y

    application_name

    String

    MYAPP

    null

    This is the name of the application

    Y

    application_version

    String

    3.0.9.1

    Null

    This is the version number for your application

    Y

    bundle_name

    String

    com.bundlename

    null

    This is the name of the bundle

    Y

    carrier_country

    String

    fr

    null

    This is the ISO 3166-1 Alpha 2 code

    Y

    carrier_name

    String

    Free

    null

    This is the name of the cell phone carrier

    Y

    conn_type

    String

    WIFI

    null

    This is the type of data connection

    N

    device_info

    JSON Object

    null

    This is the device information structure. The structure will be explained further down

    N

    event

    JSON Object

    null

    This is the list of events that you are sending

    N

    screen_resolution

    String

    1024x768

    null

    This is the screen resolution of the device

    N

    sdk_version

    String

    partner ID value

    null

    This is the version of your SDK

    Y

    source

    String

    ADVERTISER_SDK

    "ADVERTISER_SDK"

    This is the source of the information contained in the payload. This parameter is MANDATORY

    Y

    user_language

    String

    fr

    null

    This is the ISO 3166-1 Alpha 2 code

    N

    viewport_size

    String

    400x300

    null

    This is the actual size of the viewport of the app

    N

    device_type

    String

    Handheld | Tablet

    null

    Device Type accepts 3 enums [ tablet, handheld, null ]

    N

    version

    String

    2

    2

    Version

    Y

    Device_info Mapping Table

    Key Name

    Type

    Sample Value

    Default value

    Description

    Mandatory

    os

    String

    iPhone OS

    null

    This is the name of the OS running on the phone

    Value MUST be "iOS","Android", or "Windows".

    Y

    Os_version

    String

    8.1.3

    null

    This is the version of the OS running on the phone

    N

    Os_language

    String

    fr

    "en"

    This is the ISO 3166-1 Alpha 2 code

    N

    Ip_v4

    String

    3.0.9.1

    null

    This is the ipv4 of the device

    Y

    Ip_v6

    String

    null

    This is the ipv6 of the device

    N

    make

    String

    Apple

    null

    This is the name of the maker

    Y

    model

    String

    iPhone

    null

    This is the name of the device

    Y

    Timezone_offset

    Integer

    -25200

    0

    This is the timezone offset in seconds

    N

    country

    String

    fr

    null

    This is the ISO 3166-1 Alpha 2 code

    Y

    Id_info

    JSON Object

    null

    This is the device information structure. The structure will be explained further down

    Y

    user_agent

    String

    "Mozilla/5.0 (iPad; CPU OS 9_1 like Mac OS X) "

    null

    This is a device user agent.

    N

    ID_info Mapping Table

    Key Name

    Type

    Sample Value

    Default values

    Description

    Mandatory

    Dpid

    String

    9AEF8C48-91F3-47A9-A400-B474621CFC0D

    null

    This is the device id of the device (either idfa, aid, wpid)

    Y

    Dpid_sha1

    String

    897a26ccf206628432d1667845e11b0cec0fee21

    null

    This is the sha1 value for dpid

    Y

    Dpid_md5

    String

    163fb576035dd3cfb9c01dd43f0e862c

    null

    This is the md5 value for dpid

    Y

    aid

    String

    null

    This is the Google Advertising Identifier (sometimes called GAID in the industry)

    Y

    Adv_id

    String

    null

    This is android advertising id. Since Android ID is deprecated and the field is mandatory, most clients send GAID a second time.

    Y

    Idfa

    String

    9AEF8C48-91F3-47A9-A400-B474621CFC0D

    null

    This is the idfa value for Apple

    Y

    Idfv

    String

    EA8AA54A-8BDF-4D6F-B760-703CA1820BFB

    null

    This is the idfv value for Apple

    Y

    Opt_out

    Boolean

    false

    false

    Tells the system whether the user has opted out of tracking or not.

    N

    Bluetooth_status

    String

    null

    This is the status of the Bluetooth code

    N

    Locale

    String

    En-US

    En-US

    This is the locale of the device

    Event Mapping Table

    Key Name

    Type

    Sample Value

    Description

    Mandatory

    Event_name

    String

    MyEventName

    This is the name of the event.

    Y

    Transaction_id

    String

    1222

    This is the transaction id, must be unique per transaction.

    Y

    Timestamp

    Long

    1431582994837

    Epoc timestamp (MUST BE MILLISECONDS)

    Y

    Key_value

    JSON Array

    {key_value:"title", string_value:"Intro to Analytics"}

    This is the structure used to pass extra parameters.

    Y

    Lat

    Long

    nul

    This is the latitude of the deviceOUTPUT = (lat X 1,000,000)

    N

    Lon

    Long

    null

    This is the longitude of the deviceOUTPUT = (lon X 1,000,000)

    N

    Session_id

    String

    4E5C09B7-73E5-406F-8140-13751FB62B1B

    This is the session id (GUID)

    Y

    Speed

    String

    null

    This is the speed of the device

    N

    JSON payload structure

    The JSON payload should have the following structure. Please note that some parameters are optional and dependent on the platform. The actual meaning of the parameters is explained later in a table. The JSON structure is also pretty complex and will be decomposed.

    Actual examples will be provided as separate files with this document in order to make it clear. Here is the list of all elements at root level. Please note that when fields are not filled, they should be appearing with a null value. All parameters are also actual string except for one exception. Nested structures will be present in subsequent tables:

    JSON format (example)

    Comments after //, (M)= Mandatory fields, (O)= Optional fields

    {

    "application_id": "9E7662CA-2E05-41AB-8E4C-50E9F626FF49", // This is the ID available on Settings page on the Portal (M)

    "application_name": "MyApp", // This is the name of your App (O)

    "application_user_id": "", // This can be null (O)

    "application_version": null, // This is the version of your App if available, or else null (O)

    "bundle_name": "testbundle", // Please add the bundle id of your app or leave as test (O)

    "carrier_country": null, // Please add carrier country if available, else null (O)

    "carrier_name": null, // Please add carrier name if available, else null (O)

    "conn_type": "WIFI", // Please add connection type if available, else null (O)

    "device_info": {

    "country": "US", // Please add the country of the App download (M)

    "id_info": {

    "adv_id": null, // Please add Android advertiser ID if Android, else null (O)

    "aid": null, // Please add Android ID if Android, else null (O)

    "dpid": "9B445DD3-8510-46C2-A534-4552F07BF942", // Please add IDFA if iOS, aid or Adv_id if Android (M)

    "dpid_md5": null, // Please add md5 hash of dpid (O needed for Install Tracking)

    "dpid_sha1": null, // Please add sha1 hash of dpid (O needed for Install Tracking)

    "idfa": "9B445DD3-8510-46C2-A534-4552F07BF942", // Please add IDFA if iOS (O)

    "idfv": null, // Please add IDFV if iOS and Opt out is true (O)

    "opt_out": false, // Please add condition of user for tracking (M)

    "production_live": null, // null for S2S

    "r1_daid": null // null for S2s

    },

    "ip_v4": null, // Please add of IPv4 Address (O)

    "make": null, // Please add make of device (O)

    "model": null, // Please add model of device (O)

    "os": "iPhone OS", // Please add OS of device (M)

    "os_language": "en", // Please add OS Language of device (M)

    "os_version": null, // Please add OS version of device (O)

    "timezone_offset": null // Please add timezone offset (O)

    },

    "device_type": "HANDHELD", // Please add device type (O)

    "event_info": [

    {

    "event_name": "Application Opened", // Please add event name (M)

    "key_value": [

    {

    "key": "Engagement Type", // Please add key of custom attribute qualifying event (O)

    "string_value": "Super High " // Please add value of custom attribute qualifying event (O)

    }, // Use string_value if string, else double_value if double format

    {

    "key": "network_name", //The name of the ad network that drove the user'sinstall. This is required to be able to segment by attribution but can otherwise be left out.

    "string_value": "RadiumOne" // Replace this with the nameof the DSP, network, or exchange. This is required to be able to segment by attribution but can otherwise be left out.

    },

    {

    "key": "tracker_name", //The name of the campaign that this user's install was attributed to.This is required to be able to segment by attribution but can otherwise be left out.

    "string_value": "Campaign name here" //This is required to be able to segment by attribution but can otherwise be left out.

    },

    {

    "key": "site_id", // The name of the website or app where the ad that the end user clicked on before installing was placed.This is required to be able to segment by attribution but can otherwise be left out.

    "string_value": "Site name here" //This is required to be able to segment by attribution but can otherwise be left out.

    }

    ],

    "lat": 340043, // Please add latitude if available (multiplied by 10000) (O)

    "lon": -1184324, // Please add longitude if available (multiplied by 10000) (O)

    "session_id": "AA", // Please add non null value for session id (M)

    "timestamp": 1431579614885, // Please add epoch timestamp of client event generation (M)

    "transaction_id": "1439830721" // Please add a non null value for transaction id (M)

    }

    ],

    "sdk_version": "S2S", // Please add sd_version as S2S always (M)

    "source": "ADVERTISER_SDK", // Please add source as ADVERTISER_SDK always (M)

    "user_language": "en", // Please add user language (O)

    "version": "2", // Please add version as 2 (M)

    "viewport_size": null // Please add viewport_size if available, else null (O)

    }

    If you post the above event to the endpoint you will receive a 200 response with the message well done!

    View Article
  • For each end user's device we collect:

    - IDFA, WPID (windows phone ID), or Android ID- advertising opt-out- mobile network- bluetooth status- mobile country code- locale- jailbroken status of the device- OS- OS version- OS language- ip- make- model- timezone- country- application version- device type- carrier name- carrier country- connection type- screen resolution- viewport size- installed app info (android only, and optional)- bundle name- user language

    Optional when location is enabled:- lat (optional)- long (optional)- altitude (optional)- course (optional)- speed (optional)

    Event data (for all users):

    - Launch: applaunch, initiates session tracking.- First Launch: when the app starts for the first time- First Launch After Update:when the app starts for the first time after a version upgrade- Suspend: the app is put into the background state- Resume: the app returns from the background state- Application Opened: recorded when the app is opened and can measure when your app is opened after a message is sent- Session Start: a new session begins. Not displayed in portal but used to calculate session information which is displayed.- Session End:a session ends; includes a Session Length attribute with the session length in seconds. Not displayed in portal but used to calculate session information which is displayed.

    Event data (custom):

    We can track virtually anything that might happen in your app, but it's up to you to set up this custom tracking.

    View Article
  • What events should I track in Mobile Analytics?

    Setting up event tracking is the single most important part of getting your Mobile Analytics instance up and running. It is imperative that your event tracking strategy be well thought out, as these events will form the foundation for all of your reporting going forward. This document outlines the process by which you should set up event tracking so you can make the most out of insights from your app.

    Table of Contents:

    Getting started with Mobile Analytics

    Step 1: Map out your app goals and KPIs

    Step 2: Identify all events and attributes to track

    Key things to consider when creating your list of events and attributes

    Step 3: Work with your developer to create events in Mobile Analytics

    Creating Events

    Default Events

    Standard Events

    Custom Events

    Advanced setup for custom events:

    Scenario 1: Tracking consistent events across multiple pages or screens

    Scenario 2: Tracking events that are unique per page

    Scenario 3: Omit attributes and values entirely

    Getting started with Mobile Analytics

    Step 1: Map out your app goals and KPIs

    The very first step in setting up your Mobile Analytics solutions is to sit down with key stakeholders and your marketing/analytic teams to map out the Key Performance Indicators (KPI's) for your app.

    Note: These goals/KPIs/reports will vary considerably depending on your vertical and your particular approach. There is no one-size-fits-all solution.

    Step 2: Identify all events and attributes to track

    Once you have an understanding of all your app KPIs, youll have a much better sense for what information you need to see and measure. Thinking about all the reports that will help you track KPIs, create a list of all the events you need to track (i.e.: user made a purchase) along with relevant attributes (i.e.: user spent $50).

    Key things to consider when creating your list of events and attributes

    What are the critical parts of the user experience in my app?

    Where am I losing users? What features need improvement?

    Does my user base spending a lot of time with one feature? This could mean something is broken and/or a time suck for users... but it could also mean they love the feature and are very engaged. Breaking out the tracking will help you tell the difference.

    What will I learn by tracking this event?

    How is it relevant to my KPI's?

    What attributes of the event are important? For example, a Transaction event should at minimum include the value of the transaction and the names or ID's of the item or items purchased, but depending on your monetization model might benefit from other contextual info as well.

    What events would define a valuable audience? What sort of segments do you want to push to your media campaigns?

    What reports will I want to see? What information do I need to collect in order to produce those reports?

    Step 3: Work with your developer to create events in Mobile Analytics

    Once you have identified all the events and attributes you want to track, work with you app developer to create these events in Mobile Analytics. Note below that there are some events that will be tracked by default in your Mobile Analytics.

    Creating Events

    There are 3 types of events in Mobile Analytics:

    Default events

    Standard events

    Custom events

    Most integrations involve all three event types.

    Default Events

    Default events are tracked automatically. No further action needed to record the information below.

    Launch - fired when the app starts

    First Launch - fired when the app starts for the first time

    First Launch After Update -fired when the app starts for the first time after a version upgrade

    Application Opened - fired when your app is opened

    Session Start - fired when a new session starts. Sessions are defined as a period of continuous activity so you may have multiple sessions tracked for a single app open if users frequently send your app to the background between uses instead of quitting out of it entirely.

    Session End - fired when a session ends; includes a Session Length attribute with the session length in seconds

    Note: Tracking only default events will be insufficient for virtually every deployment and will cripple your reporting. Per above, you should also be tracking standard and/or custom events that make sense for your particular apps KPIs.

    Standard Events

    To make reporting easier, we have standardized data formatting for a few very common events, these include:

    Login: Tracks a user login within the app

    Registration: Records a user registration within the app

    Facebook connect: Track this when the user allows access to Facebook services

    Twitter connect: Track this when the user allows access to Twitter services

    User Info: This event enables you to send user profiles to the backend. Please do not send us personally identifiable information!

    Upgrade: Tracks an application version upgrade

    Trial Upgrade: Tracks an application upgrade from a trial version to a full version

    Screen View: Basically, a page view, it provides info about that screen

    Transaction: A purchase

    Delete Cart

    Add To Cart

    Delete From Cart

    Custom Events

    You are not limited to these predefined events, and in fact virtually every deployment will have at least a few custom events. The key elements of custom event tracking are:

    The Event name or label: this is label that will be used in the Analytics dashboard to refer to your events. It should be descriptive and give at least basic information about what is happening without being overly precise. For example, the event name "pageView" is too vague and doesn't provide any useful information about what the user is actually doing. A better event name would be "productPageView" which tells you that the end user is viewing a product.

    Attribute label: Our mobile analytics dashboard allows you to input custom attributes about your events. These attributes are typically contextual information that add segmentation options. So, for example, if I'm tracking a "productPageView" event I might want the attribute label to be "productName"

    Attribute values: The values of the attribute will be descriptive and correspond to the selected label. So if I set the attribute label to "productName" the value could be the actual name or id of the product being viewed.

    This combination creates a record for an event named "productPageView" and in Segmentation, Funnels, Retention, and the other various reports I would be able to segment out instances of that productPageView event according to the name of the product being viewed.

    Note that the you should never use variables that are unique per user in your naming of events, attributes, or values. Doing so will break the mobile analytics dashboard.

    Advanced setup for custom events:

    Every app is a bit different and so is every company's reporting requirements. Depending on those requirements you may want to customize your naming conventions for your custom events. Here are three different scenarios where this could be applicable.

    Scenario 1: Tracking consistent events across multiple pages or screens

    Do you have a few consistent events that are tracked across multiple pages and want to group your reports based on the action being completed instead of the page it is being completed from? In this case you might use the following:

    Event name: the name of the action being completed

    Attribute label: pageName

    Attribute value: the name of the page where the user completed the action.

    You would be able to generate a report of all the places where people clicked a button (for example) and then segment it by the pages that they did so from. Depending on the reporting you want, it might be a good thing to be able to lump together all clicks of a common button across multiple pages.

    Scenario 2: Tracking events that are unique per page

    If the buttons and interactions on each page are unique, you might instead lump all interactions on a page together in a single event and then segment out the specific events.

    Event name: viewMore

    Attribute label: actionsTaken

    Attribute value: the name of the actions taken on the view more page.

    Scenario 3: Omit attributes and values entirely

    This has the advantage of surfacing all the pertinent info at the top level and making reporting setup a bit faster. The down side is that you would not be able to lump similar events together across pages the way you can with scenario 1 or lump together sets of events from a single page as in scenario 2.

    Event name: Concatenate Page name + event name, so for example "productDetail_addToCart"

    Attribute label: none

    Attribute value: none

    If you are new to Analytics and need a hand figuring this out, please reach out to our Sales Engineering team and we will be happy to help make sure you get the data you need and are able to implement tracking quickly and easily.

    View Article
  • The process for integrating the Mobile Analytics SDK is very straightforward. The steps are as follows:

    Create your RadiumOne Mobile Analytics account (if you have not already done so).

    Create a profile for your app. Note that in our solution Android, iOS, and Windows versions of an app are part of the same app profile and that our reporting allows you to filter by platform or lump them all together as needed.

    Import the library into your project

    Initialize and configure the SDK using your Application ID from the RadiumOne dashboard. https://github.com/radiumone/r1-connect-titanium

    Track in-app events - Do not skip this step! If you are unsure what to track, check out our guide to setting up tracking.

    Track any web-view events that are initiated from within the app

    Set up Attribution tracking, either via your existing attribution analytics provider or via our Kochava integration. This is only available to our media clients. If you want to use our Kochava integration please check with your RadiumOne account manager.

    Set up Smart link initialization if you want to enable deferred deep linking from our Smart links solution.

    Test the SDK implementation by opening your dev build of the app and performing all the tracked actions and then going to the RadiumOne dashboard and validating that the data appears. Note that there may be a delay of ~30 minutes for data to visualize in the dashboard.

    For full step by step instructions, please refer to our documentation on Github.iOS: https://github.com/radiumone/r1-connect-demo-iOS

    Android: https://github.com/radiumone/r1-connect-demo-Android

    Windows: https://github.com/radiumone/r1-connect-demo-WP/tree/master/R1ConnectDemo

    Phonegap: https://github.com/radiumone/r1-connect-demo-phonegap

    Titanium:

    View Article
  • The short answer is yes.

    Connect gives you deep in-app analytics, full attribution data across all networks via our partnership with Kochava, push notification management, and sophisticated location analysis in a single tool. All of that functionality exists completely independent of our advertising products.

    If youare using Activate, Connect provides fantastic targeting data that will make it more effective. Think of the two products as adjacent office towers with a bridge between them. They are independent but mutually reinforcing and you can send as much or as little data from one to the other as makes sense for your business.

    View Article
  • Connect has two fundamentally different methods to work with user actions.

    Event tracking comes from the Analytics side of the product's pedigree and is fundamentally about tracking historical data. By contrast, Tagging in Connect comes from the Push Messaging side and is about what people are doing now.

    So what does that mean for you as you set up your Connect implementation? Let's use some concrete examples to illustrate them.

    Say a user is in your app and adds an item to their cart

    View Article
  • System Requirements

    SDK Initialization

    Import Files

    Link the Static Library

    Initialize the SDK

    Advanced Settings

    Analytics Activation

    1. System Requirements

    The R1 Connect SDK supports all mobile and tablet devices running iOS 6.0 or newer with a base requirement of Xcode 4.5 used for development (Xcode 6.0 or newer is recommended). The downloadable directory (see below " a. Import Files ") contains the library and headers for the R1 Connect SDK.

    The library supports the following architectures (iOS version 6.0 and higher):

    -arm7, arm7s, arm64 for deploying to physical devices

    -i386, x86_64 for Simulator testing

    2. SDK Initialization

    a. Import Files

    Download the r1connect lib files: git clone [email protected] :radiumone/r1-connect-demo-iOS.git

    Open your iOS project in Xcode.

    Select File -> Add Files to [YOUR XCODE PROJECT] project

    Select all header files in the appropriate "Lib" Folder from the repo you just cloned. The "Bitcode Lib" is built for Xcode 7 version (with bitcode support). The "Non-Bitcode Lib" should only be used if you are building with Xcode 6.

    When the dialog box appears, check the Copy Items into destination groups folder checkbox.

    b. Link the Static Library

    Go to "Build Phases" and make sure LibR1Connect.a file is set in the Link Binary With Libraries section. If absent, please add it.

    Make sure you add:

    libsqlite3.dylib

    CoreLocation.framework

    CoreBluetooth.framework

    AdSupport.framework

    CoreTelephony.framework

    SystemConfiguration.framework

    Verify that the Background Modes switch is turned on in the Capabilities tab for your target.

    Also, it is important to add an entry to the 'Other Linker Flags' setting in your application's Build Settings in Xcode. Add '-ObjC' to the 'Other Linker Flags' setting if it is not already present. This is a common required flag when integrating static libraries with your code.

    Integrate with your Swift project

    If you are using Swift in your project and you want to use R1 Connect SDK in your swift code you should:

    Open Build Settings for your project

    Find Swift Compiler - Code Generation section

    Add path to R1SDK-Bridging-Header.h file to Objective-C Bridging Header.

    For example if SDK located in R1SDK folder inside your root project directory path will be $(PROJECT_DIR)/R1SDK/R1SDK-Bridging-Header.h

    c. Initialize the SDK

    You will need to initialize the R1 Connect Library in your App Delegate.

    Import the required header files (Only for Objective C code)

    At the top of your application delegate include any required headers:

    #import "R1SDK.h"

    #import "R1Emitter.h"

    Initialize the R1Connect Instance

    Note:The sdk.applicationID value is found in your RadiumOne Connect Dashboard under the Settings > Application tab. Do NOT use your Apple app ID, doing so will break your integration and prevent data from being sent.

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    R1SDK *sdk = [R1SDK sharedInstance];

    // Initialize SDK

    sdk.applicationId = @"YOUR APPLICATION ID";

    return YES;

    }

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    let sdk = R1SDK.sharedInstance();

    // Initialize SDK

    sdk.applicationId = "YOUR APPLICATION ID";

    return true

    }

    d.Feature Configuration

    The following is a list of configuration parameters for the R1 Connect SDK. Most of these contain values that are sent to the tracking server to help identify your app on our platform and to provide analytics on sessions and location.

    Configuration Parameters

    applicationUserId

    Optional current user identifier.

    [R1SDK sharedInstance].applicationUserId = @"12345";

    R1SDK.sharedInstance().applicationUserId = "12345";

    cookieMapping

    Enable or disable cookie mapping. By default is NO. Setting this first party cookie will enable RadiumOne to be effective in targeting the user for advertising campaigns run on behalf of the Publisher. Only enable this setting if you plan to run advertising with RadiumOne.

    [R1SDK sharedInstance].cookieMapping = YES;

    R1SDK.sharedInstance().cookieMapping = true;

    deferredDeeplinkScheme

    Enable deferred Deeplinking via Po.st.Value is the app registered URL scheme. This is optional but recommended.

    [R1SDK sharedInstance].deferredDeeplinkScheme = @"your app scheme";

    R1SDK.sharedInstance().deferredDeeplinkScheme = "your app scheme";

    location

    The current user location coordinates. Use only if your application already uses location services.

    [R1SDK sharedInstance].location = [locations lastObject];

    R1SDK.sharedInstance().location = ;

    locationService

    If your application did not use location information before this SDK installation, you can use locationService in this SDK to enable or disable it:

    [R1SDK sharedInstance].locationService.enabled = YES;

    R1SDK.sharedInstance().locationService.enabled = true;

    N.B. - The Connect locationService uses the Location Manager in iOS. For deployment on iOS 8 and newer, it is required that the application's property list (plist) file include one of the two following keys:

    NSLocationAlwaysUsageDescription

    //provide location updates whether the user is actively using the application or not via infrequent background location updates

    // OR

    NSLocationWhenInUseUsageDescription

    //provide location updates only while the user has your application as the foreground running app

    These are string values that need to include a description suitable to present to a user. The description should explain the reason the application is requesting access to the user's location. Therefore, description you give should try to incorporate or reference the user benefit that may be possible through sharing location.

    You must import R1LocationService.h to use this feature.

    When enabled, such as in the example above, location information will be sent automatically. However, locationService doesnt fetch the location constantly. For instance, when the location is received the SDK will turn off the location in CLLocationManager and wait 10 minutes (by default) before attempting to retrieve it again. You can change this value:

    [R1SDK sharedInstance].locationService.autoupdateTimeout = 1200; // 20 minutes

    R1SDK.sharedInstance().locationService.autoupdateTimeout = 1200; // 20 minutes

    appName

    The application name associated with the emitter. By default, this property is populated with the CFBundleName string from the application bundle. If you wish to override this property, you must do so before making any tracking calls.

    [R1Emitter sharedInstance].appName = @"Custom application name";

    R1Emitter.sharedInstance().appName = "Custom application name";

    appId

    Default: nil

    The application identifier associated with this emitter. If you wish to set this property, you must do so before making any tracking calls. Note: that this is not your app's bundle id, like e.g. com.example.appname.

    [R1Emitter sharedInstance].appId = @"12345678";

    R1Emitter.sharedInstance().appId = "12345678";

    appVersion

    The application version associated with this emitter. By default, this property is populated with theCFBundleShortVersionString string from the application bundle. If you wish to override this property, you must do so before making any tracking calls.

    [R1Emitter sharedInstance].appVersion = @"1.0.2";

    R1Emitter.sharedInstance().appVersion = "1.0.2";

    sessionTimeout

    If positive, indicates how long, in seconds, the application must transition to the inactive or background state for before the tracker will automatically indicate the start of a new session when the app becomes active again by setting sessionStart to true. For example, if this is set to 30 seconds, and the user receives a phone call that lasts for 45 seconds while using the app, upon returning to the app, the sessionStart parameter will be set to true. If the phone call lasted 10 seconds, sessionStart will not be modified.

    To disable automatic session tracking, set this to a negative value. To indicate the start of a session anytime the app becomes inactive or backgrounded, set this to zero.

    By default, this is 30 seconds.

    [R1Emitter sharedInstance].sessionTimeout = 15;

    R1Emitter.sharedInstance().sessionTimeout = 15;

    3. Feature Activation

    a. Analytics Activation

    Setup your App Delegate

    (Only for Objective C code)

    #import "R1SDK.h"

    #import "R1Emitter.h"

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    {

    R1SDK *sdk = [R1SDK sharedInstance];

    // Initialize Analytics

    sdk.applicationId = @"YOUR APPLICATION ID"; //Ask your RadiumOne contact for an app id

    // Start SDK

    [sdk start];

    return YES;

    }

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    let sdk = R1SDK.sharedInstance();

    // Initialize Anlaytics

    sdk.applicationId = "YOUR APPLICATION ID";

    // Start SDK

    sdk.start();

    return true

    }

    View Article
  • While using the SDK toadd push messages toyour application is rather straightforward,obtaining the correct certificate from Apple to upload to the Connect portal can be confusing. Failing to upload the proper "Production" or "Development" SSL certificate can causeApple Push Notification Services to reject any push messages you create.

    The key is to:

    - know what type of codesigning you use on your application

    - create an Apple Push Notification SSL certificate on the Apple developer portal with an environment ("production" or "development") that corresponds to your codesign selection

    - download the Apple SSL certificate

    - add the certificate to your keychain

    - using keychain, export the certificate to a p12 format

    More details can be found here.

    View Article
  • Push is disabled by default. You can enable it in the Application_Launching method or later.

    Radiumone.Connect.Push.Instance.Enabled = true;

    Once enabled, you need to add Tagging in order to target your notifications.

    Push Tags

    You can specify Tags for R1 Connect SDK to send Push Notifications for certain groups of users. Tags are universal attributes that describe key information about the end user and target them with relevant messaging. Tags can be anything from the end user's gender or age to how much they've spent over their lifetime in your app to just about anything else you might think of. Tags aretracked separately from event tracking and are processed in real time.

    The maximum length of a Tag is 128 characters.

    R1 Connect SDK saves Tags. You do not have to add Tags every time the application is launched.

    Add a new Tag

    Radiumone.Connect.Push.Instance.Tags.AddTag("NEW TAG");

    Add multiple Tags

    var tags = new List<String>() { "NEW TAG 1", "NEW TAG 2" };

    Radiumone.Connect.Push.Instance.Tags.AddTags(tags);

    Remove existing Tag

    Radiumone.Connect.Push.Instance.Tags.DeleteTag("EXIST TAG");

    Remove multiple Tags

    var tags = new List<String>() { "EXIST TAG 1", "EXIST TAG 2" };

    Radiumone.Connect.Push.Instance.Tags.DeleteTags(tags);

    Get all Tags

    var currentTags = Radiumone.Connect.Push.Instance.Tags.AllTags;

    View Article
  • Endpoint:

    Production

    https://api.r1mobileconnect.com/push

    Staging

    http://stage.r1mobileconnect.com:8080

    Method:

    POST

    Authentication:

    basic (app_id:master_key)

    Content-type:

    application/json

    Accept:

    application/vnd.radiumone-v1+json

    Push JSON parameters:

    payload

    alert [String] push text

    badge [Number] badge

    sound [String] 'off'/'default'/<audio file name>

    collapse_key [String] to consolidate similar push messages (GCM)

    delay_while_idle [Boolean] (GCM)

    time_to_live [Number] number of days to expire a message if not delivered

    title [String] title in Android tray notifications (GCM)

    data [Object] set of arbitrary key/value pairs

    apns [Object] APNS specific parameters if any

    sound [String] 'off'/'default'/<audio file name>

    data [Object] set of arbitrary key/value pairs

    gcm [Object] GCM specific parameters if any

    sound [String] 'off'/'default'/<audio file name>

    data [Object] set of arbitrary key/value pairs

    target

    platform [Array<String>] list of platforms to push to; valid platform names are "ios"/"android"/"windows" /if not specified then it means all platforms

    broadcast [Boolean] true to send a broadcast push

    tags [Array<String>] list of tags

    schedule

    run_at [Date] timestamp to schedule a push for: String (iso 8601)

    Rich push parameters

    payload

    "payload": {"data": {"r1rich": <URL>}}

    Deep link parameters

    payload

    "payload": {"data": {"r1deep": <URL>}}

    Segment syntax

    Currently supported segment criteria: "location" and "tag"

    Segment operators are "and", "or" and "not"

    Operators "and" and "or" operate on arrays.

    Criterion "tag":

    {"tag": <value>}

    Criterion "location":

    {"location": {"date":{<date>}, "area":{<area>}}}

    "date" = "last"|"range"

    "last" = {"weeks"|"days"|"hours" : <number>}

    "range" = {"from": <start date>, "to": <end date>}

    "area" = "center"

    "center" = {"lon":<longitude>, "lat":<latitude>, "radius":<miles>}

    Response

    success

    status: 201{"task_id": <task_id>}

    Examples:

    By tag:

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d '{"target":{"tags":[some tag"]}, "payload":{"alert:some text"}}' https://api.r1mobileconnect.com/push

    for iOS:

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d '{"target":{"devices":{"apns":[<device token>"]}}, "payload":{"alert:some text"}}' https://api.r1mobileconnect.com/push

    for Android:

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d '{"target":{"devices":{gcm":[<registration ID>"]}}, "payload":{"alert:some text"}}' https://api.r1mobileconnect.com/push

    Broadcast for iOS Devices with Badge count 2

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d{"target":{"broadcast":true, "platform":["ios"]}, "payload":{"alert":"Good morning","badge":2}} https://api.r1mobileconnect.com/push

    Segmented Push for "Giants" tag on both iOS and Android

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d{"target":{"tags":["giants"], "platform":["ios", "android"]}, "payload":{"alert":"Go Giants"}} https://api.r1mobileconnect.com/push

    Broadcast Push on iOS with default sound

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d{"target":{"broadcast":true, "platform":["ios"]}, "payload":{"alert":"Good morning","sound":"default"}} https://api.r1mobileconnect.com/push

    Broadcast Push on iOS with sound off

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d{"target":{"broadcast":true, "platform":["ios"]}, "payload":{"alert":"Good morning","sound":"off"}} https://api.r1mobileconnect.com/push

    Segmented Rich Push for "Giants" tag on iOS opening "http://google.com"

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d{"target":{"tags":["giants"], "platform": ["ios"]}, "payload":{"alert":"Go Giants", "data":{"r1rich": " google.com "}}} https://api.r1mobileconnect.com/push

    Segmented Push for "Giants" tag on iOS scheduled for Nov 18 2015 13:41:30

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d{"target":{"tags":["giants"], "platform":["ios"]}, "payload":{"alert":"Go Giants"}, "schedule":{"run_at":"2015-11-18T13:41:30-08:00"}} https://api.r1mobileconnect.com/push

    Segmented Push for "Giants" and "Athletics"

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d{"target":{"segment": {"and": [{"tag": "giants"}, {"tag": "athletics"}]}}, "payload":{"alert":"Go Giants"}} https://api.r1mobileconnect.com/push

    Segmented Push for iOS and all users seen within 50 meters of lat 37.913034 and long -122.062355 in the last 1 day

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d{"payload": {"alert": "TTT"}, "target": {"platform": ["ios"], "segment": {"and": [{"location": {"date": {"last": {"days": 1}}, "area": {"center": {"lat": 37.913034, "radius": 50, "lon": -122.062355}}}}]}}} https://api.r1mobileconnect.com/push

    Segmented Push for iOS and "Giants" and "Athletics" tag and all users seen within 50 meters of lat 37.912 and long -122.062

    curl -u <app_id:<master key>" -H "Accept: application/vnd.radiumone-v1+json" -H "Content-Type: application/json" -d{"payload": {"alert": "TTT"}, "target": {"platform": ["ios"], "segment": {"and":[{"tag":"giants"}, {"tag":"athletics"}, {"location": {"area": {"center": {"lon": -122.062, "lat": 37.912}}}}]}}} https://api.r1mobileconnect.com/push

    View Article
  • Use the following methods to configure push notifications.

    isStarted

    Callback arguments: (bool isStarted)

    Indicates whether Push has started. Push starts automatically if you set up all the keys in config.xml.

    R1Push.isStarted(function (isStarted) {

    //...

    });

    setEnabled

    Enable or disable R1Push.

    R1Push.setEnabled(true);

    isEnabled

    Callback arguments: (bool isEnabled)

    Indicates whether R1Push is enabled.

    R1Push.isEnabled(function (isEnabled) {

    //...

    });

    getDeviceToken

    Callback arguments: (String deviceToken)

    Get the push identifier for the device. Can be null if R1Push not enabled.

    R1Push.getDeviceToken(function (deviceToken) {

    //...

    });

    setBadgeNumber

    Note: iOS only

    Set application badge number.

    R1Push.setBadgeNumber(2);

    getBadgeNumber

    Note: iOS only. For Android the callback will always be a 0 value.

    Callback arguments: (int badgeNumber)

    Get currently used badge number.

    R1Push.getBadgeNumber(function (badgeNumber) {

    //...

    });

    setTags

    Set tags for the device.

    R1Push.setTags(["Tag1", "Tag2"]);

    addTag

    Add tag for the device

    R1Push.addTag("Tag1");

    removeTag

    Remove tag from the device

    R1Push.removeTag("Tag1");

    getTags

    Callback arguments: (Array tags)

    Get the current tags.

    R1Push.getTags(function (tags) {

    //...

    });

    Events

    R1Push.deviceToken

    Notify the push deviceToken has changed

    document.addEventListener("R1Push.deviceToken", function(event) {

    // event.deviceToken

    }, false);

    R1Push.foregroundNotification

    For iOS and Android: Notify when a push notification is recieved when the application is running in the foreground

    For Windows Phone 8: Notify when a Toast notification is recieved when the application is running in the foreground

    document.addEventListener("R1Push.foregroundNotification", function(event) {

    // event - object with full information about notification

    alert(event);

    }, false);

    R1Push.backgroundNotification

    Only for iOS and Android! Notify when a push notification is received when the application is running in the background and the app is opened by this notification

    document.addEventListener("R1Push.backgroundNotification", function(event) {

    // event - object with full information about notification

    alert(event.aps.alert);

    }, false);

    R1Push.foregroundHttpNotification

    Only for Windows Phone 8: Notify when a Raw notification is recieved when the application is running in the foreground

    document.addEventListener("R1Push.foregroundHttpNotification", function(event) {

    // event - object with full information about notification

    alert(event);

    }, false);

    View Article
  • Push Notification Activation

    i. Setup Google Cloud Messaging

    ii. Initialization

    iii. Rich Push Initialization

    iv. Rich Push Customization

    v. Inbox Initialization

    vi. Deep Link Initialization

    vii. Using Tagging to Segment your Audience

    i. Setup Google Cloud Messaging

    Prerequisites for Google Cloud Messaging Setup

    This doc assumes you have already set up Google Play Services in your application project. Google Play Services is needed to use Google Cloud Messaging (GCM), the notification gateway RadiumOne Connect will use for your Android app. Also if you have not done so already, you will need to add the app you will be using to the RadiumOne Connect portal in order to add the Google API Key to it once you have generated the API Key following the steps below.

    Configuring your App for GCM

    Obtain an API key from Google

    In order to use RadiumOne Connect with your application you will need an API key from Google. We will summarize those steps here, but for more info on this process please visit GCM Getting Started here.

    1. Create a Google API project in Google APIs Console (take note of your project number which is the value after #project: it will be used later as your GCM sender ID)

    2. Enable the GCM Service

    3. Create a new Server key in the Google APIs Console page under API Access. when prompted, allow access to ip 0.0.0.0/0

    4. Copy the key, it is used for GCM Connection Servers and for RadiumOne Connect setup

    Setting up the API Key on R1 Connect

    1. Please make sure you are signed into your account on RadiumOne Connect and go to the application you want to add this API key to.

    2. Next, in the side menu go to Dev Tools > Push Services > Google Cloud Messaging.

    3. Add your API Key to the API Key field and click Save.

    If it saved correctly you will see a green badge with a white checkmark in it. Now your app is setup with GCM.

    ii. Initialization

    To make sure push notifications work correctly, please follow these steps:

    Configure the r1connect.properties file in your project:

    push.sender_id You will need to enter the project number you received when creating your Google API project.

    push.client_key=<YOUR CLIENT KEY> - Obtain your Client key from the "Settings" page in your Connect dashboard.

    push.enable This defaults to true and will enable or disable push notifications after you start your application

    Create a class that inherits from the class Application (or you can use an existing one in the project)

    To enable an action such as opening the app when a notification is clicked, create a class that inherits from BroadcastReceiver and add the necessary logic to it. If you are okay with the default, which closes the notification upon pressing it, then no further coding is required.

    public class TestPushReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {

    try{

    Context applicationContex = context.getApplicationContext();

    if ( intent != null && intent.getAction() != null){

    if (intent.getAction().equals(R1Push.OPENED_NOTIFICATION)){

    Intent openIntent = new Intent(context, ShowNotificationActivity.class);

    openIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);

    if ( intent.getExtras() != null ){

    openIntent.putExtras(intent.getExtras());

    }

    applicationContex.startActivity(openIntent);

    }

    }

    } catch (Exception ex){

    }

    }

    }

    Then update the application class:

    public class MyApplication extends Application{

    @Override

    public void onCreate() {

    super.onCreate();

    // drawable in notification bar

    R1Emitter.getInstance().setNotificationIconResourceId(this, R.drawable.notification_icon);

    // custom BroadcastReceiver

    R1Emitter.getInstance().setIntentReceiver(this, TestPushReceiver.class);

    R1Emitter.getInstance().connect(this);

    }

    }

    If you don't have an application class yet, create it and don't forget to reference it inside the Manifest:

    <!-- android:name of application tag must be full application name that was created in first step.-->

    <application

    android:name="com.example.r1connecttestapplication.MyApplication"

    android:allowBackup="true"

    android:icon="@drawable/ic_launcher"

    android:label="@string/app_name"

    android:theme="@style/AppTheme" >

    If you want to create your own notifications you have to create a class that implements R1NotificationBuilder interface and write your notification builder like in the example below:

    public class CustomNotificationBuilder implements R1NotificationBuilder {

    private int lastId;

    @Override

    public Notification createNotification(Context context, Intent intent) {

    if ( context == null || intent == null){

    return null;

    }

    String text = intent.getStringExtra(R1PushNotificationManager.NOTIFICATION_KEY);

    String title = intent.getStringExtra(R1PushNotificationManager.NOTIFICATION_TITLE);

    if ( text != null ){

    NotificationCompat.Builder nb = new NotificationCompat.Builder(context)

    .setAutoCancel(true)

    .setTicker(text)

    .setContentText(text)

    .setWhen(System.currentTimeMillis());

    if (!TextUtils.isEmpty(title)){

    nb.setContentTitle(title);

    } else {

    nb.setContentTitle("My Application Name");

    }

    nb.setDefaults(Notification.DEFAULT_ALL);

    nb.setSmallIcon(R.drawable.ic_launcher);

    Notification notification = nb.build();

    lastId++;

    return notification;

    }

    return null;

    }

    @Override

    public int getLastNotificationId() {

    return lastId;

    }

    }

    After that add this line just before R1Emitter.getInstance().connect(this) in your application class:

    R1Emitter.getInstance().setNotificationBuilder(new CustomNotificationBuilder());

    Update the manifest as shown below.

    Add the following inside the application tag:

    <!-- PUSH -->

    <receiver android:name="com.google.android.gms.gcm.GcmReceiver"

    android:exported="true"

    android:permission="com.google.android.c2dm.permission.SEND">

    <intent-filter>

    <action android:name="com.google.android.c2dm.intent.RECEIVE" />

    <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

    <!-- name must be your applicationPackage -->

    <category android:name="###YOUR APPLICATION PACKAGE###" />

    </intent-filter>

    </receiver>

    <service

    android:name="com.radiumone.emitter.gcm.RegistrationIntentService"

    android:exported="false" />

    <service

    android:name="com.radiumone.emitter.gcm.R1ConnectGCMListenerService"

    android:exported="false">

    <intent-filter>

    <action android:name="com.google.android.c2dm.intent.RECEIVE" />

    </intent-filter>

    </service>

    <service

    android:name="com.radiumone.emitter.gcm.R1ConnectInstanceIDListenerService"

    android:exported="false">

    <intent-filter>

    <action android:name="com.google.android.gms.iid.InstanceID" />

    </intent-filter>

    </service>

    <receiver android:name="com.radiumone.emitter.push.R1PushBroadcastReceiver"

    android:exported="false">

    <intent-filter>

    <action android:name="com.radiumone.r1push.OPENED_INTERNAL"/>

    </intent-filter>

    </receiver>

    <service android:name="com.radiumone.emitter.push.R1ConnectService"/>

    <service android:name="com.radiumone.emitter.location.LocationService"/>

    //Using the class created in Step 2 (cont):

    <receiver android:name=".testpush.TestPushReceiver"

    android:exported="false">

    <intent-filter>

    <action android:name="com.radiumone.r1push.OPENED"/>

    </intent-filter>

    </receiver>

    <meta-data

    android:name="com.google.android.gms.version"

    android:value="@integer/google_play_services_version" />

    <!-- END OF PUSH -->

    Add the following inside the manifest tag:

    <!-- PUSH -->

    <!-- Permissions that are necessary for the library to work: -->

    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <uses-permission android:name="android.permission.INTERNET" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <!-- Permission to get location when using the network -->

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    <!-- Permission to get location when using GPS -->

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>

    <!-- GET Accounts permission is required to make GCM working for Android devices below 4.0.4-->

    <uses-permission android:name="android.permission.GET_ACCOUNTS" android:maxSdkVersion="14"/>

    <uses-permission android:name="android.permission.VIBRATE"/>

    <permission android:name="###YOUR APPLICATION PACKAGE###.permission.C2D_MESSAGE" android:protectionLevel="signature"/>

    <uses-permission android:name="###YOUR APPLICATION PACKAGE###.permission.C2D_MESSAGE"></uses-permission>

    <!-- END OF PUSH -->

    iii. Rich Push Initialization

    Rich push notifications send a URL that opens upon user response to a system notification. In addition to the general push setup requirements, if you would like to enable rich push notifications that include HTML/CSS/JavaScript you have to add the following data in the AndroidManifest.xml:

    <service android:name="com.radiumone.emitter.richpush.R1RichPushService" />

    <activity

    android:name="com.radiumone.emitter.richpush.activity.R1RichPushActivity"

    android:configChanges="orientation|keyboardHidden|screenSize"

    android:label="@string/title_activity_rich_push"

    android:launchMode="singleTask"

    android:parentActivityName=".MainActivity"

    android:theme="@style/AppThemeCustomNoTitle"

    android:windowSoftInputMode="stateHidden">

    <meta-data

    android:name="android.support.PARENT_ACTIVITY"

    android:value=".MainActivity" />

    </activity>

    The parent activity for rich activity is the view accessed when selecting the back button. Older platforms may require the meta-data attributes above.

    @style/AppThemeCustomNoTitle is the window style. If you would like to present the view without a title, use the following style:

    <style name="AppThemeCustomNoTitle" parent="AppTheme">

    <item name="android:windowNoTitle">true</item>

    </style>

    Users that select rich push notifications will by default start com.radiumone.emitter.richpush.activity.R1RichPushActivity and start the HTML content.

    iv. Rich Push Customization

    If you want to customize Rich Push then update your custom BroadcastReceiver ( TestPushReceiver ):

    Bundle extras = intent.getExtras();

    if (extras != null) {

    // getting rich push ID - no rich push id means that push is simple and no rich content for it

    String richPushId = extras.getString(R1PushNotificationManager.RICH_PUSH);

    if (TextUtils.isEmpty(richPushId)) {

    openIntent = new Intent(applicationContext, ShowNotificationActivity.class);

    } else {

    openIntent = new Intent(applicationContext, R1RichPushActivity.class);

    openIntent.putExtra(R1RichPush.R1_RICH_PUSH_ID, richPushId);

    }

    }

    In this scenario, we check for rich push id in extras and start different activities for rich and regular push.

    You can change the activity for Rich Push if you want to use fragments, toolbar, or another activity that you want to use as the Rich Push Activity. See the code below:

    import android.app.Activity;

    import android.content.Intent;

    import android.os.Bundle;

    import android.text.TextUtils;

    import android.util.Log;

    import android.view.ViewGroup;

    import com.radiumone.emitter.richpush.R1RichPush;

    import com.radiumone.emitter.richpush.R1RichPushManager;

    import com.radiumone.emitter.richpush.R1RichPushMessage;

    import com.radiumone.emitter.richpush.R1RichPushWebView;

    public class CustomPushActivity extends Activity implements R1RichPushManager.OnMessageReceivedListener{

    private String richPushId;

    private R1RichPushWebView webView;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    Bundle extras = getIntent().getExtras();

    if ( extras == null ){

    Log.i(CustomPushActivity.class.getSimpleName(), "Wrong parameters for " + R1RichPushActivity.class.getSimpleName());

    finish();

    return;

    }

    richPushId = extras.getString(R1RichPush.R1_RICH_PUSH_ID);

    }

    @Override

    protected void onNewIntent(Intent intent) {

    setIntent(intent);

    Bundle extras = getIntent().getExtras();

    if ( extras == null ){

    Log.i(CustomPushActivity.class.getSimpleName(), "Wrong parameters for " + R1RichPushActivity.class.getSimpleName());

    finish();

    return;

    }

    richPushId = extras.getString(R1RichPush.R1_RICH_PUSH_ID);

    loadRichPush();

    }

    private void loadRichPush() {

    if (TextUtils.isEmpty(richPushId)){

    Log.i(CustomPushActivity.class.getSimpleName(), "No rich_push_id in extras");

    finish();

    return;

    }

    R1RichPushMessage message = R1RichPushManager.getR1RichPushManager().getR1RichPushMessage(this, richPushId, this);

    if ( message != null ) {

    webView = new R1RichPushWebView(this);

    webView.setLayoutParams( new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

    setContentView(webView);

    if ( message.getStatus() == R1RichPushMessage.RESULT_OK ) {

    webView.loadR1RichPush(message);

    } else {

    Log.i(CustomPushActivity.class.getSimpleName(), "Error while getting rich push message");

    finish();

    }

    }

    }

    @Override

    protected void onPause() {

    super.onPause();

    if ( webView != null ){

    webView.onPause();

    }

    if ( !TextUtils.isEmpty(richPushId)) {

    R1RichPushManager.getR1RichPushManager().removeListener(richPushId, this);

    }

    }

    @Override

    protected void onResume() {

    super.onResume();

    if ( webView != null ){

    webView.onResume();

    } else {

    loadRichPush();

    }

    }

    @Override

    public void onResult(R1RichPushMessage message) {

    if ( message != null && message.getStatus() == R1RichPushMessage.RESULT_OK) {

    if (richPushId != null && richPushId.equals(message.getId())) {

    runOnUiThread( new Runnable() {

    @Override

    public void run() {

    loadRichPush();

    }

    });

    }

    } else {

    Log.i(CustomPushActivity.class.getSimpleName(), "No Connection while getting rich push message");

    finish();

    }

    }

    @Override

    public void onError(R1RichPushMessage message) {

    Log.i(CustomPushActivity.class.getSimpleName(), "Error while getting rich push message");

    finish();

    }

    }

    The important line in this class is

    //get R1RichPushMessage from R1RichPushManager

    R1RichPushMessage message = R1RichPushManager.getR1RichPushManager().getR1RichPushMessage(this, richPushId, this);

    where

    R1RichPushManager.getR1RichPushManager().getR1RichPushMessage(Context context, String richPushId, R1RichPushManager.OnMessageReceivedListener receiveListener);

    To make Rich Push work you have to use the following method of R1RichPushWebView:

    webView.loadR1RichPush(message);

    Next register your activity in AndroidManifest.xml (do not forget service android:name="com.radiumone.emitter.richpush.R1RichPushService" because it necessary for both custom and default rich push activity).

    <service android:name="com.radiumone.emitter.richpush.R1RichPushService" />

    <activity

    android:name="###YOUR APPLICATION PACKAGE###.CustomRichPushActivity"

    android:configChanges="orientation|keyboardHidden|screenSize"

    android:label="@string/title_activity_rich_push"

    android:launchMode="singleTask"

    android:parentActivityName=".MainActivity"

    android:windowSoftInputMode="stateHidden">

    <meta-data

    android:name="android.support.PARENT_ACTIVITY"

    android:value=".MainActivity" />

    </activity>

    Then add this line just before R1Emitter.getInstance().connect(this) in your application class:

    R1Emitter.getInstance().setRichPushActivity(CustomRichPushActivity.class);

    Now rich push will be opened in your custom activity.

    v. Inbox Initialization

    The Inbox provides an easy interface to house past rich-push messages sent to your users so they can still be visible to users that have disabled push messaging or who want to come back to them later.

    If you want to enable inbox functionality you need to create a fragment or an activity that shows a list of Inbox messages and listen for messages updates in the Inbox. This reference source code shows how to implement Activity in which you can show and delete messages from Inbox (this activity must be registered in your AndroidManifest.xml). This also assumes that Rich Push functionality mentioned above is already integrated.

    public class R1InboxActivity extends Activity implements R1InboxManager.OnInboxUpdateListener, AdapterView.OnItemClickListener {

    // ListView for inbox messages

    private ListView listView;

    // Adapter for showing messages in listview

    private R1InboxMessageAdapter adapter;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    // creating ListView programmatically, but it can be layout from xml

    listView = new ListView(this);

    listView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

    listView.setId(android.R.id.list);

    // creating Inbox adapter

    adapter = new R1InboxMessageAdapter(this);

    listView.setAdapter(adapter);

    // sets click listener for this Activity

    listView.setOnItemClickListener(this);

    // this line is for correct working delete buttons in list

    listView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);

    setContentView(listView);

    }

    // method gets inbox messages and set to adapter for showing in list

    private void loadMessages() {

    final R1InboxMessage[] messages = R1InboxManager.getInboxManager().getR1InboxMessages(this);

    runOnUiThread( new Runnable() {

    @Override

    public void run() {

    if ( adapter != null ){

    adapter.setInboxMessages(messages);

    }

    }

    });

    }

    @Override

    protected void onPause() {

    super.onPause();

    // remove inbox update listener when Activity goes to pause state

    R1InboxManager.getInboxManager().setInboxUpdateListener(null);

    }

    @Override

    protected void onStart() {

    super.onStart();

    // calls SDK onStart method

    R1Emitter.getInstance().onStart(this);

    }

    @Override

    protected void onStop() {

    super.onStart();

    // calls SDK onStop method

    R1Emitter.getInstance().onStop(this);

    }

    @Override

    protected void onResume() {

    super.onResume();

    // set inbox update listener when Activity resumes. After that all updates in inbox will invoke callback inboxUpdated() in this Activity

    R1InboxManager.getInboxManager().setInboxUpdateListener(this);

    // get actual messages after pause

    loadMessages();

    }

    @Override

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    if ( adapter != null ) {

    // get R1InboxMessage object for pressed listview position

    R1InboxMessage inboxMessage = adapter.getItem(position);

    // call inboxMessageOpen() method for correct opening and showing inbox message

    R1InboxManager.getInboxManager().inboxMessageOpen(this, inboxMessage);

    }

    }

    @Override

    public void inboxUpdated() {

    // get actual messages after inbox updated

    loadMessages();

    }

    @Override

    public void inboxUpdateError() {

    Log.i(getClass().getSimpleName(),"Inbox update error");

    }

    // adapter for showing Inbox messages

    private class R1InboxMessageAdapter extends BaseAdapter {

    private final LayoutInflater inflater;

    // array of R1InboxMessage

    private R1InboxMessage[] listOfMessages;

    public R1InboxMessageAdapter(Context context){

    listOfMessages = new R1InboxMessage[0];

    inflater = (LayoutInflater)context.getSystemService(LAYOUT_INFLATER_SERVICE);

    }

    @Override

    public int getCount() {

    if ( listOfMessages == null ){

    return 0;

    }

    return listOfMessages.length;

    }

    @Override

    public R1InboxMessage getItem(int position) {

    return listOfMessages[position];

    }

    @Override

    public long getItemId(int position) {

    return position;

    }

    @Override

    public View getView(int position, View convertView, ViewGroup parent) {

    View view = convertView;

    ViewHolder viewHolder = null;

    if (view == null) {

    // Layout for inbox item. Will be shown further.

    view = inflater.inflate(R.layout.r1_inbox_item, null);

    viewHolder = new ViewHolder();

    viewHolder.alert = (TextView)view.findViewById(R.id.alert);

    viewHolder.title = (TextView)view.findViewById(R.id.title);

    viewHolder.dateTime = (TextView)view.findViewById(R.id.datetime);

    viewHolder.readIndicator = view.findViewById(R.id.read_indicator);

    viewHolder.delete = (Button)view.findViewById(R.id.delete_button);

    // set OnClickListener for delete button

    viewHolder.delete.setOnClickListener( new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    // if tag for pressed button is an instance of R1InboxMessage you have to call inboxMessageDelete method in R1InboxManager for correct deletion of message

    Object tag = v.getTag();

    if ( tag instanceof R1InboxMessage ) {

    R1InboxManager.getInboxManager().inboxMessageDelete(R1InboxActivity.this, (R1InboxMessage) tag);

    }

    }

    });

    view.setTag(viewHolder);

    } else {

    viewHolder = (ViewHolder)view.getTag();

    }

    R1InboxMessage message = getItem(position);

    // set Tag for delete button. This needs for knowing what message must be deleted after button pressed.

    viewHolder.delete.setTag(message);

    viewHolder.alert.setText(message.getAlert());

    viewHolder.title.setText(message.getTitle());

    viewHolder.dateTime.setText( dateTimeLocalised( message.getDateTime() ));

    // checks that message is not readed and show it

    if ( message.getReadState() == R1RichPushMessage.READ ){

    viewHolder.readIndicator.setVisibility(View.INVISIBLE);

    } else {

    viewHolder.readIndicator.setVisibility(View.VISIBLE);

    }

    return view;

    }

    public void setInboxMessages(R1InboxMessage[] inboxMessages){

    this.listOfMessages = inboxMessages;

    notifyDataSetChanged();

    }

    }

    private static class ViewHolder {

    TextView title;

    TextView alert;

    TextView dateTime;

    Button delete;

    View readIndicator;

    }

    private String dateTimeLocalised(long dateTime){

    dateTime -= TimeZone.getDefault().getOffset(dateTime);

    return DateFormat.getDateTimeInstance().format(dateTime);

    }

    }

    Layout R.layout.r1_inbox_item.xml from source code above:

    <?xml version="1.0" encoding="utf-8"?>

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="?listPreferredItemHeight"

    android:orientation="horizontal"

    android:padding="8dp">

    <View

    android:id="@+id/read_indicator"

    android:layout_width="10dp"

    android:layout_height="10dp"

    android:layout_alignParentLeft="true"

    android:layout_alignParentStart="true"

    android:layout_gravity="center_vertical"

    android:layout_margin="8dp"

    android:background="@drawable/shape" />

    <LinearLayout

    android:id="@+id/notification_content"

    android:layout_width="0dp"

    android:layout_height="wrap_content"

    android:layout_gravity="center_vertical"

    android:layout_toEndOf="@+id/read_indicator"

    android:layout_toLeftOf="@+id/delete_button"

    android:layout_toRightOf="@+id/read_indicator"

    android:layout_toStartOf="@+id/delete_button"

    android:orientation="vertical">

    <TextView

    android:id="@+id/title"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:ellipsize="marquee"

    android:maxLines="1" />

    <TextView

    android:id="@+id/alert"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:ellipsize="marquee"

    android:maxLines="2" />

    </LinearLayout>

    <Button

    android:id="@+id/delete_button"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_alignParentEnd="true"

    android:layout_alignParentRight="true"

    android:focusable="false"

    android:text="Delete" />

    <TextView

    android:id="@+id/datetime"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_below="@+id/notification_content"

    android:layout_gravity="bottom"

    android:layout_toLeftOf="@+id/delete_button"

    android:layout_toStartOf="@+id/delete_button" />

    </RelativeLayout>

    R1InboxMessage is an object that has the following methods to display details of inbox messages:

    datetime

    inboxMessage.getDateTime()

    Returns inbox message timestamp as epoch time in milliseconds

    title

    inboxMessage.getTitle()

    Returns inbox message title text

    alert

    inboxMessage.getAlert()

    Returns inbox message alert text

    readState

    inboxMessage.getReadState()

    Returns the read state of an inbox message, values are R1InboxMessage.READ/ R1InboxMessage.UNREAD

    To display a number of unread messages use the following code:

    int unread = R1InboxManager.getInboxManager().getInboxUnreadCount(context);

    To be notified for realtime updates of the number of unread messages you need to register R1InboxManager.OnInboxUpdateListener. To stop this updates you need to unregister it:

    R1InboxManager.getInboxManager().setInboxUpdateListener( new R1InboxManager.OnInboxUpdateListener() {

    @Override

    public void inboxUpdated() {

    // inbox updated

    }

    @Override

    public void inboxUpdateError() {

    // error occurred while inbox updated

    }

    });

    vi. Deep Link Initialization

    Deep linking push messages open up a designated view in an application upon user response to a system notification. To properly handle deep link push receipts, please read Androids documentation on registering a custom URL scheme here: http://developer.android.com/guide/topics/manifest/data-element.html

    vii. Segment your Audience

    You can specify Tags for R1 Connect SDK to send Push Notifications for certain groups of users. You can then send Push Notifications to users with specific tags.

    The maximum length of a Tag is 128 characters.

    R1 Connect SDK saves Tags. You do not have to add Tags every time the application is launched.

    Add a new Tag

    R1Push.getInstance(context).addTag("tag");

    Add multiple Tags

    for ( String tag: tags) {

    R1Push.getInstance(this).addTag(tag);

    }

    Remove existing Tag

    R1Push.getInstance(context).removeTag("tag");

    Remove multiple Tags

    for ( String tag: tags) {

    R1Push.getInstance(this).removeTag(tag);

    }

    Replace all existing Tags

    R1Push.getInstance(context).setTags(Arrays.asList("tag1","tag2"));

    Get all Tags

    String[] allTags = R1Push.getInstance(context).getTags(context);

    Automatically created Tags

    date_of_launch_dd_mm_yyyy: Replace dd_mm_yyyy with the date you want to target. Date is in your account timezone. one_time_app_users: Users who have only launched the app once

    Automatically created Segments

    Lapsed Users > 7 Days Lapsed Users > 14 Days Lapsed Users > 21 Days Lapsed Users > 30 Days

    If you are targeting devices below Android version 4.0.4, you need to also add the following permission:

    <uses-permission android:name="android.permission.GET_ACCOUNTS" />

    This is in order to enable the application to use the Google Account for communication with the Google Cloud Messaging platform (used for pushed notifications). For devices running version 4.0.4 or later, a Google account is not required anymore, therefore the permission is unnecessary.

    View Article
  • Push Notification Activation

    i. Setup Apple Push Notification Services

    ii. Initialization

    iii. Rich Push Initialization

    iv. Deep Link Initialization

    v. Using Tagging to Segment your Audience

    vi. Inbox Integration

    Push Notification Activation

    i. Setup Apple Push Notification Services

    Prerequisites for Apple Push Notification Services Setup

    The Importance of Setting your App as in Production or in Development

    When creating or editing an app on RadiumOne Connect you can set the status of the app to either Production or Development. Production status for an app is considered to be a live app that is in the hands of real users and will have notifications and other data running on live servers. A Development status for an app is one that you are still performing testing on and will not be viewed by any real-life audiences because it will stay on test servers.

    In the context of push notifications, it is important to know this difference because Apple will treat these two servers separately. Also device tokens for Development will not work on Production and vice versa. We recommend a Development app version and Production app version for your app on RadiumOne Connect to keep Push SSL certificates separate for each. You can also continue testing and experimenting on one app without worrying about it affecting your live app audience in any way.

    iOS Developer Program Enrollment

    This doc assumes that you are enrolled in the iOS Developer Program. If you are not, please enroll here. Being in the Apple Developer Program is a required component to have your iOS app communicate with the RadiumOne Connect service for push notifications and is necessary for the next step of setting up your app with the Apple Push Notification Service (APNs). It is also essential that you have Team Agent role access in the iOS Developer Program to complete this process.

    Configuring your App for Apple Push Notifications

    Apple Developer Members Center

    Make sure you are logged into the Apple Developer Members Center. Once you are logged in you can locate your application in the Identifiers folder list.

    Registered App ID

    If you have not registered an App ID yet it is important that you do so now. You will need to click the + symbol, fill out the form, and check the Push Notifications checkbox. Please keep in mind it is possible to edit these choices after the App ID is registered.

    You can expand the application and when doing so you will see two settings for push notifications. They will have either yellow or green status icons like here:

    You will need to click Edit to continue. If the Edit button is not visible it is because you do not have Team Agent role access. This role is necessary for getting an SSL certificate.

    Creating an SSL Certificate

    To enable the Development or Production Push SSL Certificate please click Edit. (It is important to note that each certificate is limited to a single app, identified by its bundle ID and limited to one of two environments, either Development or Production. Read more info here.)

    You will see a Create Certificate button, after clicking it you will see the Add iOS Certificate Assistant. Please follow the instructions presented in the assistant which includes launching the Keychain Access application, generating a Certificate Signing Request (CSR), generating an SSL Certificate, etc.

    If you follow the assistant correctly, after downloading and opening the SSL Certificate you should have it added under My Certificates or Certificates in your Keychain Access application. Also when you are returned to the Configure App ID page the certificate should be badged with a green circle and the label Enabled.

    Exporting the SSL Certificate

    If not already in the Keychain Access app that contains your certificate, please open it and select the certificate that you just added. Once you select the certificate go to File > Export Items and export it as a Personal Information Exchange (.p12) file. When saving the file be sure to use the Personal Information Exchange (.p12) format.

    Emailing your SSL certificate

    After downloading your 2 certificates (one for production, one for development), please send them to your RadiumOne account manager (with certificate passwords if you choose to add any).

    ii. Initialization

    Setup your App Delegate

    (Only for Objective C code)

    #import "R1SDK.h"

    #import "R1Emitter.h"

    #import "R1Push.h"

    #import "R1WebCommand.h" // required for rich push

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    {

    R1SDK *sdk = [R1SDK sharedInstance];

    // Initialize SDK

    sdk.applicationId = @"Application ID"; //Ask your RadiumOne contact for an app id

    // Initialize Push Notification

    sdk.clientKey = @"Your Client Key"; //Ask your RadiumOne contact for a client key

    [[R1Push sharedInstance] handleNotification:[launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey]

    applicationState: application.applicationState];

    [[R1Push sharedInstance] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |

    UIRemoteNotificationTypeSound |

    UIRemoteNotificationTypeAlert)];

    // Start SDK

    [sdk start];

    return YES;

    }

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    let sdk = R1SDK.sharedInstance();

    // Initialize Anlaytics

    sdk.applicationId = "Application ID"; //Ask your RadiumOne contact for an app id

    // Initialize Push Notification

    sdk.clientKey = "Your Client Key"; //Ask your RadiumOne contact for a client key

    R1Push.sharedInstance().delegate = self;

    var remoteNotificationInfo: NSDictionary? = nil

    if launchOptions != nil {

    remoteNotificationInfo = (launchOptions![UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary)!;

    }

    R1Push.sharedInstance().handleNotification(remoteNotificationInfo as? [NSObject : AnyObject], applicationState: application.applicationState);

    R1Push.sharedInstance().registerForRemoteNotificationTypes([.Alert,.Badge,.Sound]);

    // Start SDK

    sdk.start();

    return true

    }

    Register for Remote Notifications

    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

    [[R1Push sharedInstance] registerDeviceToken:deviceToken];

    }

    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {

    [[R1Push sharedInstance] failToRegisterDeviceTokenWithError:error];

    }

    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

    [[R1Push sharedInstance] handleNotification:userInfo applicationState:application.applicationState];

    }

    func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {

    R1Push.sharedInstance().registerDeviceToken(deviceToken);

    }

    func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {

    R1Push.sharedInstance().failToRegisterDeviceTokenWithError(error);

    }

    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {

    R1Push.sharedInstance().handleNotification(userInfo, applicationState: application.applicationState);

    }

    Push is disabled by default. You can enable it in the application:didFinishLaunchingWithOptions method or later.

    [[R1Push sharedInstance] setPushEnabled:YES];

    R1Push.sharedInstance().pushEnabled = true;

    NOTE: If you enabled it in the application:didFinishLaunchingWithOptions method, the Push Notification AlertView will be showed at first application start.

    iii. Rich Push Initialization

    Rich Push Notifications send a URL that opens in a WebView upon user response to a system notification. No set up is required for this feature.

    Please note that iOS 9 devices require use of HTTPS. iOS 8 and previous versions still support HTTP. Please ensure that you send HTTPS if iOS 9 devices may receive the message.

    iv. Deep Link Initialization

    Deep linking Push Notifications open up a designated view in an application upon user response to a system notification. To properly handle deep link push receipts, please read Apple's documentation: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html#//apple_ref/doc/uid/TP40007072-CH6-SW10 http://wiki.akosma.com/IPhone_URL_Schemes

    v. Segment your Audience

    You can specify Tags for R1 Connect SDK to send Push Notifications to certain groups of users.

    The maximum length of a Tag is 128 characters.

    R1 Connect SDK saves Tags. You do not have to add Tags every time the application is launched.

    Add a new Tag

    [[R1Push sharedInstance].tags addTag:@"NEW TAG"];

    R1Push.sharedInstance().tags.addTag("NEW TAG");

    Add multiple Tags

    [[R1Push sharedInstance].tags addTags:@[ @"NEW TAG 1", @"NEW TAG 2" ]];

    R1Push.sharedInstance().tags.addTags(["NEW TAG 1", "NEW TAG 2"]);

    Remove existing Tag

    [[R1Push sharedInstance].tags removeTag:@"EXIST TAG"];

    R1Push.sharedInstance().tags.removeTag("EXIST TAG");

    Remove multiple Tags

    [[R1Push sharedInstance].tags removeTags:@[ @"EXIST TAG 1", @"EXIST TAG 2" ]];

    R1Push.sharedInstance().tags.removeTags([ "EXIST TAG 1", "EXIST TAG 2" ]);

    Replace all existing Tags

    [R1Push sharedInstance].tags.tags = @[ @"NEW TAG 1", @"NEW TAG 2" ];

    or

    [[R1Push sharedInstance].tags setTags:@[ @"NEW TAG 1", @"NEW TAG 2" ]];

    R1Push.sharedInstance().tags.tags = ["NEW TAG 1", "NEW TAG 2"];

    Get all Tags

    NSArray *currentTags = [R1Push sharedInstance].tags.tags;

    let currentTags = R1Push.sharedInstance().tags.tags;

    Automatically created Tags

    date_of_launch_dd_mm_yyyy: Replace dd_mm_yyyy with the date you want to target. Date is in your account timezone. one_time_app_users: Users who have only launched the app once

    Automatically created Segments

    Lapsed Users > 7 Days Lapsed Users > 14 Days Lapsed Users > 21 Days Lapsed Users > 30 Days

    vi. Inbox Integration

    The Inbox provides an easy interface to house past rich-push messages sent to your users so they can still be visible to users that have disabled push messaging or who want to come back to them later.

    If you want to enable inbox functionality, you need to use R1Inbox class and import R1Inbox.h header at the top of your class file (Only for Objective C code):

    #import "R1Inbox.h"

    If you want to add some label or button with count of unread or total Inbox messages, you should implement -(void) inboxMessageUnreadCountChanged or -(void) inboxMessagesDidChanged (func inboxMessageUnreadCountChanged() orfunc inboxMessagesDidChanged() for swift) methods from R1InboxMessagesDelegate protocol in your class. After that, add your class as delegate to [R1Inbox sharedInstance].messages (R1Inbox.sharedInstance().messages for swift).

    - (void) addInboxMessagesDelegate

    {

    [[R1Inbox sharedInstance].messages addDelegate:self];

    }

    -(void) inboxMessageUnreadCountChanged

    {

    NSString *btnTitle = [NSString stringWithFormat:@"Inbox (%lu unread)", (unsigned long)[R1Inbox sharedInstance].messages.unreadMessagesCount];

    [self.inboxButton setTitle:btnTitle forState:UIControlStateNormal];

    }

    func addInboxMessagesDelegate() {

    R1Inbox.sharedInstance().messages.addDelegate(self);

    }

    func inboxMessageUnreadCountChanged() {

    let btnTitle = String.init(format: "Inbox unread cound: %d", R1Inbox.sharedInstance().messages.unreadMessagesCount);

    inboxButton?.setTitle(btnTitle, forState: .Normal);

    }

    Do not forget to remove your class from delegates when your class gets deallocated:

    - (void) dealloc

    {

    [[R1Inbox sharedInstance].messages removeDelegate:self];

    //...

    }

    deinit {

    R1Inbox.sharedInstance().messages.removeDelegate(self);

    //...

    }

    To display the list of Inbox messages, you should create your own ViewController to provide required customization. In this case, this screen would not look foreign to your application.

    You can see the sample of Inbox implementation in DemoApplication project in files R1SampleInboxTableViewCell.h,R1SampleInboxTableViewCell.m, R1SampleInboxViewController.h, R1SampleInboxViewController.m (for Objective C) and in DemoApplicationSwift project in files R1SampleInboxTableViewCell.swift, R1SampleInboxViewController.swift (for swift)

    R1SampleInboxTableViewCell.h

    #import <UIKit/UIKit.h>

    @class R1InboxMessage;

    @interface R1SampleInboxTableViewCell : UITableViewCell

    // Sets or Gets R1InboxMessage object and configures cell for it

    @property (nonatomic, strong) R1InboxMessage *inboxMessage;

    - (id) initWithReuseIdentifier:(NSString *)reuseIdentifier;

    // Calculates the height of the cell

    + (CGFloat) heightForCellWithInboxMessage:(R1InboxMessage *) inboxMessage cellWidth:(CGFloat) cellWidth;

    @end

    R1SampleInboxTableViewCell.m

    #import "R1SampleInboxTableViewCell.h"

    #import "R1Inbox.h"

    @interface R1SampleInboxTableViewCell ()

    @property (nonatomic, strong) UIView *unreadMarker;

    @property (nonatomic, strong) UILabel *alertLabel;

    @property (nonatomic, strong) NSDateFormatter *dateFormatter;

    @end

    @implementation R1SampleInboxTableViewCell

    - (id) initWithReuseIdentifier:(NSString *)reuseIdentifier

    {

    self = [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];

    if (self)

    {

    self.alertLabel = [[UILabel alloc] initWithFrame:CGRectZero];

    self.alertLabel.numberOfLines = 0;

    self.alertLabel.lineBreakMode = NSLineBreakByWordWrapping;

    [self.contentView addSubview:self.alertLabel];

    self.unreadMarker = [[UIView alloc] initWithFrame:CGRectZero];

    self.unreadMarker.layer.cornerRadius = 3;

    self.unreadMarker.backgroundColor = [UIColor blueColor];

    [self.contentView addSubview:self.unreadMarker];

    self.textLabel.font = [UIFont boldSystemFontOfSize:14];

    self.alertLabel.font = [UIFont systemFontOfSize:14];

    self.detailTextLabel.textAlignment = NSTextAlignmentRight;

    self.dateFormatter = [[NSDateFormatter alloc] init];

    [self.dateFormatter setDateStyle:NSDateFormatterShortStyle];

    [self.dateFormatter setTimeStyle:NSDateFormatterMediumStyle];

    }

    return self;

    }

    // Configures the cell for displaying Inbox Message

    - (void) setInboxMessage:(R1InboxMessage *)inboxMessage

    {

    if (_inboxMessage == inboxMessage)

    {

    [self configureUnreadMarker];

    return;

    }

    _inboxMessage = inboxMessage;

    self.textLabel.text = inboxMessage.title;

    self.alertLabel.text = inboxMessage.alert;

    self.detailTextLabel.text = [self.dateFormatter stringFromDate:inboxMessage.createdDate];

    [self configureUnreadMarker];

    [self setNeedsLayout];

    }

    // Shows or hides unread marker view

    - (void) configureUnreadMarker

    {

    if ([self.unreadMarker isHidden] != _inboxMessage.unread)

    return;

    [self.unreadMarker setHidden:!_inboxMessage.unread];

    }

    - (void) layoutSubviews

    {

    [super layoutSubviews];

    self.unreadMarker.frame = CGRectMake(4, (self.contentView.bounds.size.height - 6)/2, 6, 6);

    self.detailTextLabel.frame = CGRectMake(0, 0, self.contentView.bounds.size.width-10, 20);

    if (self.textLabel.text == nil)

    {

    self.alertLabel.frame = CGRectMake(15, 15, self.contentView.bounds.size.width-20, self.contentView.bounds.size.height-20);

    }else

    {

    self.textLabel.frame = CGRectMake(15, 15, self.contentView.bounds.size.width-20, 20);

    self.alertLabel.frame = CGRectMake(15, 35, self.contentView.bounds.size.width-20, self.contentView.bounds.size.height-45);

    }

    }

    // Calculates the height of the cell

    + (CGFloat) heightForCellWithInboxMessage:(R1InboxMessage *) inboxMessage cellWidth:(CGFloat) cellWidth

    {

    CGFloat height = 25;

    if (inboxMessage.title != nil)

    height += 20;

    if (inboxMessage.alert != nil)

    {

    if ([inboxMessage.alert respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)])

    {

    NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];

    paragraph.lineBreakMode = NSLineBreakByWordWrapping;

    NSDictionary *attributes = @{NSFontAttributeName : [UIFont systemFontOfSize:14],

    NSParagraphStyleAttributeName: paragraph};

    height += [inboxMessage.alert boundingRectWithSize:CGSizeMake(cellWidth-20, 100)

    options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)

    attributes:attributes

    context:nil].size.height;

    }else

    {

    height += [inboxMessage.alert sizeWithFont:[UIFont systemFontOfSize:14]

    constrainedToSize:CGSizeMake(cellWidth-20, 100)

    lineBreakMode:NSLineBreakByWordWrapping].height;

    }

    height += 1;

    }

    if (height < 50)

    return 50;

    return height;

    }

    @end

    R1SampleInboxViewController.h

    #import <UIKit/UIKit.h>

    #import "R1Inbox.h"

    @protocol R1SampleInboxViewControllerDelegate;

    @interface R1SampleInboxViewController : UITableViewController <R1InboxMessagesDelegate>

    @property (nonatomic, assign) id<R1SampleInboxViewControllerDelegate> inboxDelegate;

    - (id) initInboxViewController;

    @end

    @protocol R1SampleInboxViewControllerDelegate <NSObject>

    - (void) sampleInboxViewControllerDidFinished:(R1SampleInboxViewController *) sampleInboxViewController;

    @end

    R1SampleInboxViewController.m

    #import "R1SampleInboxViewController.h"

    #import "R1SampleInboxTableViewCell.h"

    #import "R1Inbox.h"

    @interface R1SampleInboxViewController ()

    @property (nonatomic, strong) R1InboxMessages *inboxMessages;

    @end

    @implementation R1SampleInboxViewController

    // Initialize UITableViewController

    - (id) initInboxViewController

    {

    self = [super initWithStyle:UITableViewStylePlain];

    if (self)

    {

    self.inboxMessages = [R1Inbox sharedInstance].messages;

    [self updateTitle];

    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone

    target:self action:@selector(closeInboxViewController)];

    }

    return self;

    }

    // Called when user presses 'Done' button

    - (void) closeInboxViewController

    {

    [self.inboxDelegate sampleInboxViewControllerDidFinished:self];

    }

    // Updates the title of ViewController with number of unread messages

    - (void) updateTitle

    {

    if (self.inboxMessages.unreadMessagesCount == 0)

    self.navigationItem.title = @"Inbox";

    else

    self.navigationItem.title = [NSString stringWithFormat:@"Inbox (%lu unread)", (unsigned long)self.inboxMessages.unreadMessagesCount];

    }

    - (void) viewWillAppear:(BOOL)animated

    {

    [super viewWillAppear:animated];

    [self updateTitle];

    // Add this view controller to the list of delegates when it appears

    [self.inboxMessages addDelegate:self];

    }

    - (void) viewDidDisappear:(BOOL)animated

    {

    [super viewDidDisappear:animated];

    // Remove this view controller from the list of delegates when it disappears

    [self.inboxMessages removeDelegate:self];

    }

    #pragma mark - Table view data source

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;

    }

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    {

    // Returns the total number of Inbox messages

    return self.inboxMessages.messagesCount;

    }

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    {

    // Returns the calculated height of the cell for R1InboxMessage object in row

    return [R1SampleInboxTableViewCell heightForCellWithInboxMessage:[self.inboxMessages.messages objectAtIndex:indexPath.row]

    cellWidth:self.tableView.frame.size.width];

    }

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    {

    R1SampleInboxTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];

    if (cell == nil)

    {

    cell = [[R1SampleInboxTableViewCell alloc] initWithReuseIdentifier:@"Cell"];

    }

    // Sets up the cell for displaying R1InboxMessage object

    cell.inboxMessage = [self.inboxMessages.messages objectAtIndex:indexPath.row];

    return cell;

    }

    - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    {

    R1InboxMessage *message = [self.inboxMessages.messages objectAtIndex:indexPath.row];

    // Shows Inbox message when user interacts to the cell

    [[R1Inbox sharedInstance] showMessage:message

    messageDidShow:^{

    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];

    }];

    }

    - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath

    {

    return UITableViewCellEditingStyleDelete;

    }

    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

    {

    R1InboxMessage *message = [self.inboxMessages.messages objectAtIndex:indexPath.row];

    [self.inboxMessages deleteMessage:message];

    }

    #pragma mark - R1InboxMessagesDelegate methods

    // This method called when the list of Inbox messages gets updated

    - (void) inboxMessagesWillChanged

    {

    [self.tableView beginUpdates];

    }

    // This method called when any item in the list of Inbox messages gets changed (modified, inserted or removed)

    - (void) inboxMessagesDidChangeMessage:(R1InboxMessage *) inboxMessage

    atIndex:(NSUInteger) index

    forChangeType:(R1InboxMessagesChangeType)changeType

    newIndex:(NSUInteger) newIndex

    {

    switch (changeType)

    {

    case R1InboxMessagesChangeInsert:

    [self.tableView insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:index inSection:0] ]

    withRowAnimation:UITableViewRowAnimationAutomatic];

    break;

    case R1InboxMessagesChangeDelete:

    [self.tableView deleteRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:index inSection:0] ]

    withRowAnimation:UITableViewRowAnimationAutomatic];

    break;

    case R1InboxMessagesChangeUpdate:

    ((R1SampleInboxTableViewCell *)[self.tableView cellForRowAtIndexPath: [NSIndexPath indexPathForRow:index inSection:0] ]).inboxMessage = [self.inboxMessages.messages objectAtIndex:index];

    break;

    default:

    break;

    }

    }

    // This method called when the changes to list of Inbox messages are over

    - (void) inboxMessagesDidChanged

    {

    [self.tableView endUpdates];

    }

    // This method called when the number of unread Inbox messages gets changed

    - (void) inboxMessageUnreadCountChanged

    {

    [self updateTitle];

    }

    @end

    R1SampleInboxViewController.swift

    import UIKit

    protocol R1SampleInboxViewControllerDelegate {

    func sampleInboxViewControllerDidFinished(sampleInboxViewController: R1SampleInboxViewController);

    }

    class R1SampleInboxViewController: UITableViewController, R1InboxMessagesDelegate {

    var inboxMessages: R1InboxMessages?

    var inboxDelegate: R1SampleInboxViewControllerDelegate?;

    override func viewDidLoad() {

    super.viewDidLoad()

    inboxMessages = R1Inbox.sharedInstance().messages;

    updateTitle();

    }

    func updateTitle() {

    if (inboxMessages?.unreadMessagesCount == 0) {

    navigationItem.title = "Inbox";

    } else {

    navigationItem.title = String.init(format: "Inbox (%lu unread)", (inboxMessages?.unreadMessagesCount)!);

    }

    }

    override func viewWillAppear(animated: Bool) {

    updateTitle();

    inboxMessages?.addDelegate(self);

    }

    override func viewDidDisappear(animated: Bool) {

    inboxMessages?.removeDelegate(self);

    }

    @IBAction func closeButtonPressed(sender: UIBarButtonItem) {

    inboxDelegate?.sampleInboxViewControllerDidFinished(self);

    }

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    return 1

    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return Int((inboxMessages?.messagesCount)!);

    }

    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

    let message : R1InboxMessage = (inboxMessages?.messages[indexPath.row])! as! R1InboxMessage;

    return R1SampleInboxTableViewCell.heightForCell(message, cellWidth: tableView.frame.size.width)

    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! R1SampleInboxTableViewCell;

    let message : R1InboxMessage = (inboxMessages?.messages[indexPath.row])! as! R1InboxMessage;

    cell.setInboxMessage(message);

    return cell

    }

    override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {

    return true

    }

    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

    if editingStyle == .Delete {

    let message : R1InboxMessage = (inboxMessages?.messages[indexPath.row])! as! R1InboxMessage;

    inboxMessages?.deleteMessage(message);

    }

    }

    // MARK: - Table view delegate

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    let message : R1InboxMessage = (inboxMessages?.messages[indexPath.row])! as! R1InboxMessage;

    R1Inbox.sharedInstance().showMessage(message) { () -> Void in

    tableView.deselectRowAtIndexPath(indexPath, animated: true)

    }

    }

    // MARK: - R1InboxMessagesDelegate

    func inboxMessagesWillChanged() {

    tableView.beginUpdates()

    }

    func inboxMessagesDidChangeMessage(inboxMessage: R1InboxMessage!, atIndex index: UInt, forChangeType changeType: UInt, newIndex: UInt) {

    if (changeType == UInt(R1InboxMessagesChangeInsert)) {

    tableView.insertRowsAtIndexPaths([ NSIndexPath.init(forRow: Int(index), inSection: 0)], withRowAnimation: .Automatic);

    } else if (changeType == UInt(R1InboxMessagesChangeDelete)) {

    tableView.deleteRowsAtIndexPaths([ NSIndexPath.init(forRow: Int(index), inSection: 0)], withRowAnimation: .Automatic);

    } else if (changeType == UInt(R1InboxMessagesChangeUpdate)) {

    let cell = tableView.cellForRowAtIndexPath(NSIndexPath.init(forRow: Int(index), inSection: 0)) as! R1SampleInboxTableViewCell;

    let message : R1InboxMessage = (inboxMessages?.messages[Int(index)])! as! R1InboxMessage;

    cell.setInboxMessage(message);

    }

    }

    func inboxMessagesDidChanged() {

    tableView.endUpdates()

    }

    func inboxMessageUnreadCountChanged() {

    updateTitle()

    }

    }

    R1SampleInboxTableViewCell.swift

    import UIKit

    class R1SampleInboxTableViewCell: UITableViewCell {

    @IBOutlet weak var unreadMarkerView: UIView?

    @IBOutlet weak var alertLabel: UILabel?

    @IBOutlet weak var messageLabel: UILabel?

    @IBOutlet weak var dateLabel: UILabel?

    var dateFormatter: NSDateFormatter?

    func setInboxMessage(inboxMessage: R1InboxMessage) {

    unreadMarkerView?.hidden = !inboxMessage.unread;

    self.messageLabel?.text = inboxMessage.title;

    self.alertLabel?.text = inboxMessage.alert;

    self.dateLabel?.text = dateFormatter?.stringFromDate(inboxMessage.createdDate);

    }

    override func awakeFromNib() {

    super.awakeFromNib()

    dateFormatter = NSDateFormatter?.init();

    dateFormatter?.dateStyle = .ShortStyle;

    dateFormatter?.timeStyle = .MediumStyle;

    }

    static func heightForCell(inboxMessage: R1InboxMessage, cellWidth: CGFloat) -> CGFloat {

    var height: CGFloat = 16+40;

    if (inboxMessage.alert != nil) {

    let paragraph : NSMutableParagraphStyle = NSMutableParagraphStyle.init();

    paragraph.lineBreakMode = .ByWordWrapping;

    height += inboxMessage.alert!._bridgeToObjectiveC().boundingRectWithSize(CGSize.init(width: cellWidth-16-15, height: 100), options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName : UIFont.systemFontOfSize(14), NSParagraphStyleAttributeName: paragraph], context: nil).size.height;

    }

    return height;

    }

    }

    In Objective C example, initialize the R1SampleInboxViewController with the following method:

    [[R1SampleInboxViewController alloc] initInboxViewController]

    View Article
  • If you've scheduled push messages and your messages were sent ahead or behind the scheduled time, your account settings may be configured for a different time zone.

    To edit your global time zone, go to the account settings page on the portal (after you've signed in) and update the Time Zone field. Hit Save Changes when you're done.

    Your settings on this field control all components of push messaging, from scheduling to reporting.

    View Article
  • System Requirements

    SDK Initialization

    Import the Library

    Initialize the SDK in All Activities

    Configure the SDK

    Update the manifest

    Advanced Settings

    1. System Requirements

    The R1 Connect SDK supports all mobile and tablet devices running Android 2.3 and above. Google Play Services must be 4.0 or above. We have two different SDK versions that support Google Play Services <6.5 and 6.5. Please ensure that you download the version that best applies to your application.

    Known Incompatibilities:

    Proguard Java Optimizer breaks the Connect SDK and prevents data from being sent back to our servers.

    2. SDK Initialization

    a. Import the library to your project

    Please start by downloading the demo project: git clone https://github.com/radiumone/r1-connect-demo-Android

    Copy SdkLib/LibR1Connect.jar into the libs directory of your project. All mobile and tablet devices running Android 2.3. and above are supported.

    If you have not registered your application in R1 Connect, please do so now.

    In Android studio, the build.gradle should include the library, android-support-library-v4 library and Google Play Services as a dependency.

    dependencies {

    compile files('libs/LibR1Connect.jar')

    compile 'com.android.support:support-v4:20.+'

    compile com.google.android.gms:play-services:4.3.+'

    }

    b. Initialize the SDK in all Activities

    The following steps will explain how to integrate R1 Connect to enable event tracking.

    Import the emitter in all your application activities:

    import com.radiumone.emitter.R1Emitter;

    And override onStart and onStop methods for each activity:

    @Override

    protected void onStart() {

    super.onStart();

    R1Emitter.getInstance().onStart(this);

    }

    @Override

    protected void onStop() {

    super.onStop();

    R1Emitter.getInstance().onStop(this);

    }

    Create a class that extends the Application class (or use an existing one), and initialize the SDK in its onCreate method:

    package com.example.yourpackagename;

    import com.radiumone.emitter.R1Emitter;

    import android.app.Application;

    public class TestApplication extends Application{

    @Override

    public void onCreate() {

    super.onCreate();

    R1Emitter.getInstance().connect(this);

    }

    }

    c. Configure the SDK

    To configure how the library will be used in your project you will need to create a file called r1connect.properties in the assets directory of your project.

    app_id=<YOUR APPLICATION_ID>

    #enable or disable cookie mapping. Default is false. Setting this first party cookie will enable RadiumOne to be effective in targeting the user for advertising campaigns run on behalf of the Publisher. Only enable this setting if you plan to run advertising with RadiumOne.

    cookieMapping=false

    4. Set Configuration Options

    #enable deferred deep linking. Value is the app's registered URI scheme.deferred_deeplink_scheme=value

    #default value of analytics is set to false. Set this flag to true to enable analytics.

    analytics.enable=true

    #allow location tracking by gps

    analytics.enable_gps=false

    #location update timeout for analytics sdk. Default 600 sec

    analytics.location_update_time=600

    #location update distance for analytics sdk. Default 100 meters

    analytics.location_update_distance=100

    #allow location tracking in background for analytics sdk. Default false

    analytics.location_in_background=false

    #prevent location tracking for analytics sdk

    analytics.disable_sdk_location=false

    ##PUSH SETTINGS

    push.client_key=<YOUR CLIENT KEY>

    # default value for push when application starts -- set to false to use the SDK without push

    push.enable=true

    As you can see in the example above, it will contain the following:

    app_id You will need to enter the App ID you received when creating your app on R1 Connect (found under Dev Tools -> Keys & Secrets)

    cookieMapping enable or disable cookie mapping. Default is false. Setting this first party cookie will enable RadiumOne to be effective in targeting the user for advertising campaigns run on behalf of the Publisher. Only enable this setting if you plan to run advertising with RadiumOne.

    push.client_key You will need to enter the App Key you received when creating your app on R1 Connect (found under Dev Tools -> Keys & Secrets)

    analytics.enable - set to "true" enables analytics in the SDK and otherwise disables it.

    analytics.disable_sdk_location - when set to true it disables the use of analytics sdk tracking location. It is useful if you want to use your own tracking location. You can pass a location object like so: R1Emitter.getInstance().trackLocation(location);

    analytics.enable_gps when set to true it enables the use of device GPS to get location (only if GPS is enabled in device settings), when false only the network is used for analytics sdk

    analytics.location_update_time set the timeout between location updates for analytics sdk

    analytics.location_update_distance set the change in distance for location updates for analytics sdk

    analytics.location_in_background set whether or not the location is allowed in analytics sdk to be sent while the app is in the background

    advertising_enabled set whether or not the application is displaying advertisements. A value of true prevents the SDK from accessing the Advertising Id to comply with Google's advertising policy when advertisements are served within the application (outside of the SDK).

    deferred_deeplink_scheme enable deferred deeplinking, value is the app registered scheme.

    d. Update the manifest

    In your manifest, add the permissions below:

    <uses-permission android:name="android.permission.INTERNET" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    Properly declare your application class:

    <application

    android:name="com.example.yourpackagename.TestApplication"

    android:allowBackup="true"

    <service android:name="com.radiumone.emitter.location.LocationService"/>

    </application>

    e. Advanced Settings

    The following is a list of configuration parameters for the R1 Connect SDK, most of these contain values that are sent to the tracking server to help identify your app on our platform and to provide analytics on sessions and location.

    appName

    The application name associated with emitter. By default, this property is populated with the package name of the application. If you wish to override this property, you must do so before making any tracking calls.

    R1Emitter.getInstance().setApplicationName("customApplicationName");

    appId

    The application identifier associated with this emitter. By default, this property is null. If you wish to set this property, you must do so before making any tracking calls. Note that this is not your app's bundle id (e.g. com.example.appname).

    R1Emitter.getInstance().setApplicationUserId("12345");

    appVersion

    The application version associated with this emitter. By default, this property is populated with the android:versionName= string from the application AndroidManifest.xml. If you wish to override this property, you must do so before making any tracking calls.

    R1Emitter.getInstance().setAppVersion("1.0");

    sessionTimeout

    Indicates how long, in seconds, the application must transition to the inactive or background state before the tracker automatically indicates the start of a new session. When this happens and the app becomes active again it will set sessionStart to true. For example, if this is set to 30 seconds, and the user receives a phone call that lasts for 45 seconds while using the app, upon returning to the app the sessionStart parameter will be set to true. If, on the other hand, the phone call lasts 10 seconds, sessionStart will not be modified. By default, this is 30 seconds.

    R1Emitter.getInstance().setSessionTimeout(30);

    applicationUserID

    Optional current user identifier.

    R1Emitter.getInstance().setApplicationUserId("12345");

    Next step: Event Tracking

    View Article
  • Debugging Tool

    This tool allows you to verify that the events that you have set up are triggering correctly. You can access the debugging area of the portal to view the JSON events sent by your application.

    Setup

    To enable the debugging tool, you should create a flat file titled "r1DebugDevices" with a list of IDFA/AAID in "www" folder of your project. There should be one ID per line.

    Once you build the app and install it on the same test devices that you added in the r1DebugDevices file, you should see any action taken in the app appear in the debug section of the portal.

    Example

    An example can be found in Demo. To run it, copy the files:

    Demo/index.html to www/index.html

    Demo/css/* to www/css

    Demo/js/* to www/js

    View Article
  • We've added a debugging tool that allows you to check whether the SDK is sending events to our servers.

    This tool allows you to verify that the events that you have set up are triggering correctly. You can access the debugging area of the portal to view the JSON events sent by your application.

    Setup

    To enable the debugging tool, you should create a flat file titled "r1DebugDevices" with a list of GAID's (Google Advertising ID - the privacy compliant device identifier on each Android device)inside of the "assets" folder. There should be one ID per line in your file.

    Once you build the app and install it on the same test devices that you added in the DebugDevices file you can see useage data from that device appear in real time. Go tothe "Data" tab under "SDK Tools" in the left navigation bar on the page. As you navigate the applicationyou should see JSON data display in the main window on the page.

    View Article
  • a. Analytics Activation

    i. Automatic Events

    ii. Standard Events

    iii. Custom Events

    iv. In-App Webview Events

    v. Best Practices

    Analytics Activation

    i. Automatic Events

    The R1 Connect SDK will automatically capture some generic events in order to get the most meaningful data on how users interact with your application. These events are triggered when the state of the application is changed, and therefore do not require any additional code to work out of the box:

    Launch - emitted when the app starts

    First Launch - emitted when the app starts for the first time

    First Launch After Update - emitted when the app starts for the first time after a version upgrade

    Application Opened - emitted when your app is opened after a message is sent.

    Session Start - emitted when a new session starts

    Session End - emitted when a session ends; includes a Session Length attribute with the session length in seconds

    ii. Standard Events

    Standard Events cover all the main user flows (login, register, share, purchase...) in a standardized format for optimized reporting on the portal, providing a great foundation for your analytics strategy. They unlock great insights, particularly with respect to user lifetime value.

    Note: The last argument in all of the following emitter callbacks, otherInfo, is a HashMap of key,value pairs or null, which enables you to customize these events as much as you want.

    Login

    Tracks a user login within the app

    R1Emitter.getInstance().emitLogin("userId", "userName", parameters);

    // where parameters is a HashMap. Example:

    private HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("key","value");

    Registration

    Records a user registration within the app

    R1Emitter.getInstance().emitRegistration("userId", "userName", "country", "city", "state", parameters);

    // where parameters is a HashMap. Example:

    private HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("key","value");

    Facebook connect

    Allows access to Facebook services

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitFBConnect(socialPermissions, parameters);

    where permissions is a List of R1SocialPermissions:

    ArrayList<R1SocialPermission> socialPermissions = new ArrayList<R1SocialPermission>();

    socialPermissions.add( new R1SocialPermission("permission", true));

    Twitter connect

    Allows access to Twitter services

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitTConnect("userId", "username", socialPermissions, parameters);

    where socialPermissions is a list of R1SocialPermissions:

    ArrayList<R1SocialPermission> socialPermissions = new ArrayList<R1SocialPermission>();

    socialPermissions.add( new R1SocialPermission("permission", true));

    User Info

    This event enables you to send user profiles to the backend.

    UserItem userItem = new UserItem();

    userItem.userId = "userId";

    userItem.userName = "userName";

    userItem.firstName = "firstName";

    userItem.lastName = "lastName";

    userItem.email = "[email protected]";

    userItem.streetAddress = "address";

    userItem.phone = "123456";

    userItem.zip = "111111";

    userItem.city = "City";

    userItem.state = "State";

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitUserInfo(userItem, parameters);

    Upgrade

    Tracks an application version upgrade

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitUpgrade(parameters);

    Trial Upgrade

    Tracks an application upgrade from a trial version to a full version

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitTrialUpgrade(parameters);

    Screen View

    Basically, a page view, it provides info about that screen

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitAppScreen("title","description","http://www.example.com/path","example.com","path",parameters);

    Transaction

    EmitItem purchaseItem = new EmitItem();

    purchaseItem.storeId = "storeId";

    purchaseItem.storeName = "name";

    purchaseItem.transactionId = "AE3237DAA";

    purchaseItem.cartId = "ABBCCD";

    purchaseItem.orderId = "ABCDEF";

    purchaseItem.totalSale = 3.2f;

    purchaseItem.currency = "EUR";

    purchaseItem.shippingCosts = 1.8f;

    purchaseItem.transactionTax = 2.5f;

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitTransaction(purchaseItem, parameters);

    TransactionItem

    R1EmitterLineItem lineItem = new R1EmitterLineItem();

    lineItem.productId = "productId";

    lineItem.productName = "productName";

    lineItem.quantity = 5;

    lineItem.unitOfMeasure = "parts";

    lineItem.msrPrice = 1.3f;

    lineItem.pricePaid = 3.4f;

    lineItem.currency = "EUR";

    lineItem.itemCategory = "items";

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitTransactionItem("transactionItemId", lineItem, parameters);

    Create Cart

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitCartCreate("cartId", parameters);

    Delete Cart

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitCartDelete("cartId", parameters);

    Add To Cart

    R1EmitterLineItem lineItem = new R1EmitterLineItem();

    lineItem.productId = "productId";

    lineItem.productName = "productName";

    lineItem.quantity = 5;

    lineItem.unitOfMeasure = "parts";

    lineItem.msrPrice = 1.3f;

    lineItem.pricePaid = 3.4f;

    lineItem.currency = "EUR";

    lineItem.itemCategory = "items";

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitAddToCart("cartId", lineItem, parameters);

    Delete From Cart

    R1EmitterLineItem lineItem = new R1EmitterLineItem();

    lineItem.productId = "productId";

    lineItem.productName = "productName";

    lineItem.quantity = 5;

    lineItem.unitOfMeasure = "parts";

    lineItem.msrPrice = 1.3f;

    lineItem.pricePaid = 3.4f;

    lineItem.currency = "EUR";

    lineItem.itemCategory = "items";

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("custom_key","value");

    R1Emitter.getInstance().emitRemoveFromCart("cartId", lineItem, parameters);

    iii. Custom Events

    Custom events enable you to create and track specific events that are more closely aligned with your app. If planned and structured correctly, custom events can be strong indicators of user intent and behavior. Some examples include pressing the like button, playing a song, changing the screen mode from portrait to landscape, and zooming in or out of an image. These are all actions by the user that could be tracked with events.

    To include tracking of custom events for the mobile app, the following callbacks need to be included in the application code:

    // Emits a custom event without parameters

    R1Emitter.getInstance().emitEvent("Your custom event name");

    // Emits a custom event with parameters

    private HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("key","value");

    R1Emitter.getInstance().emitEvent("Your custom event name", parameters);

    iv. In-App Webview Events

    By setting up in-app webview events, you can track events that begin inside your native application but are completed in the embedded browser. To do so, you will have to embed some JavaScript in the page that you will want to fire the event, and you need to properly trigger the webview in your application.

    JavaScript Setup

    To properly fire the event from your webpage, please make the following call:

    R1Connect.emitEvent(eventName,eventParameters);

    For example, both of the following work. The use of parameters is optional.

    R1Connect.emitEvent("Test Event");

    R1Connect.emitEvent("Test Event",{"key":"value"});

    Additionally, please attach the following r1connect.js file to your webpage:

    var R1ConnectBridgePlatforms = {

    UNKNOWN: 0,

    IOS: 1,

    ANDROID: 2

    };

    window.R1Connect = {

    iosBridgeScheme: "r1connectbridge://",

    platform: R1ConnectBridgePlatforms.UNKNOWN,

    iosURLQueue: [],

    iosInProgress: false,

    buildIOSUrl: function(eventName, parameters) {

    var url = this.iosBridgeScheme + 'emit/?event=' + eventName;

    if (parameters)

    url += '&params='+JSON.stringify(parameters);

    return url;

    },

    sendURLInFrame: function(url) {

    var iframe = document.createElement("IFRAME");

    iframe.setAttribute("src", encodeURI(url));

    document.documentElement.appendChild(iframe);

    iframe.parentNode.removeChild(iframe);

    iframe = null;

    },

    emitEvent: function(eventName, parameters) {

    if (this.platform == R1ConnectBridgePlatforms.UNKNOWN) {

    if (window.R1ConnectJSInterface && window.R1ConnectJSInterface.emit)

    this.platform = R1ConnectBridgePlatforms.ANDROID;

    else

    this.platform = R1ConnectBridgePlatforms.IOS;

    }

    if (this.platform == R1ConnectBridgePlatforms.ANDROID) {

    window.R1ConnectJSInterface.emit(eventName, parameters ? JSON.stringify(parameters) : '');

    return;

    }

    var iosURL = this.buildIOSUrl(eventName, parameters);

    if (this.iosInProgress) {

    this.iosURLQueue.push(iosURL);

    return;

    }

    this.iosInProgress = true;

    this.sendURLInFrame(iosURL);

    },

    iosURLReceived: function() {

    setTimeout(function() {

    window.R1Connect._iosURLReceived();

    }, 0);

    },

    _iosURLReceived: function() {

    if (this.iosURLQueue.length == 0) {

    this.iosInProgress = false;

    return;

    }

    var iosURL = this.iosURLQueue.shift();

    this.sendURLInFrame(iosURL);

    },

    };

    Java Setup

    To properly handle the events in your application, you need to first inject R1ConnectJSInterface from the R1Connect SDK:

    import com.radiumone.emitter.javascript.R1ConnectJSInterface;

    webView.addJavascriptInterface( new R1ConnectJSInterface(), "R1ConnectJSInterface");

    You then need to enable javascript for the WebView:

    WebSettings settings = webView.getSettings();

    settings.setJavaScriptEnabled(true);

    v. Best Practices

    Event Naming Convention

    One common mistake is to parametrize event names (with user data for example). Event names should be hard-coded values that you use to segement data on a specific category of event.

    Example: "ProfileViewing"

    Avoid: "Profile Viewing - Lady Gaga's profile"

    As you may have thousands of user profiles in your database, it is preferable to keep the event name high level ("ProfileViewing") so you can run interesting anaytics on it. A high level event name will help answer a question like: How many profiles does a user visit every day on average?

    Parameter Variance

    Another common mistake is to add parameters to the event that have too many possible values. To follow up on the previous example, one may decide to add the number of profile followers as an event parameter:

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("profileFollowers",profileFollowers);

    R1Emitter.getInstance().emitEvent("ProfileViewing", parameters);

    Again, the problem here is that each profile may have any number of followers. This will fragment data too much to extract any valuable information.

    Instead, a good strategy would be to define relevant buckets that replace the need for high variance parameters. In this case it might be more relevant to separate traffic on the profiles with a lot of followers from traffic on profiles with a few followers. You could define 3 categories:

    "VERY_INFLUENTIAL" for profiles > 100,000

    "INFLUENTIAL" for profile > 10,000 and <= 100,000

    "NON_INFLUENTIAL" for profile <= 10,000

    In this case, a proper event could be:

    HashMap<String, Object> parameters = new HashMap<String, Object>();

    parameters.put("profileFollowersBucket","VERY_INFLUENTIAL");

    R1Emitter.getInstance().emitEvent("ProfileViewing", parameters);

    This will enable you to create more insightful reports.

    vi. Debugging Tool

    This tool allows you to verify that the events that you have set up are triggering correctly. You can access the debugging area of the portal to view the JSON events sent by your application.

    Setup

    To enable the debugging tool, you should create a flat file titled "r1DebugDevices" with a list of advertiser IDs inside of the "assets" folder. There should be one ID per line in your file.

    Once you build the app and install it on the same test devices that you added in the DebugDevices file, you should see any action taken in the app appear in the debug section of the portal.

    Next step: Push Notifications

    View Article
  • As of January 2016 we no longer supportGPS versions lower than 6.5.

    View Article
  • Attribution Tracking Activation

    We provide attribution tracking for free for all your campaigns, whether on or off the R1 DSP, through our partnership with Kochava. The integration is entirely server-side and requires no extra setup or work on your end. This service is a free add-on for our customers.

    If you have another attribution tracking partner that you would prefer to use instead of Kochava, please contact your Account manager and we can work to enable these integrations based on demand from our clients.

    i. Track RadiumOne Campaigns

    Please contact your Account Manager to setup R1 ad campaign as well as tracking campaigns. If you don't have one, please contact us here and one of our Account Managers will assist you.

    Once your Account Manager has set up tracking, you will start receiving attribution tracking report automatically!

    ii. Track 3rd party Campaigns

    Please contact your Account Manager to setup tracking URLs for your 3rd party campaigns. If you don't have one, please contact us here and one of our Account Managers will assist you.

    Send the list of all your media suppliers (anyone you run a mobile advertising campaign with).

    For each media supplier, your account manager will send you 2 tracking URLs (one impression tracking URL, 1 click tracking URL).

    Send each pair of URLs to the relevant Media Supplier so they can set these tracking URLs on the creatives

    You're all set and will start having access to Attribution Tracking Reports

    View Article
  • R1 Connect Library for WP

    Overview

    Downloading R1ConnectLibrary.dll allows you to begin the integration process of adding R1 Connect services to your app. It supports all mobile and tablet devices running Windows Phone 8. The file itself contains the dynamic link library (DLL) of the R1 Connect SDK for WP. The library supports the following architectures:

    arm

    x86

    Setup

    The following steps will explain how to integrate with R1 Connect to enable both push notifications and event tracking. You have the option to use the R1 Connect Demo as a sample app project to begin with or you can use your own app. Once you have downloaded the R1 Connect Library from this repo you can add it to the same directory as your project.

    Required Libraries

    R1 Connect SDK required protobuf-net.dll library. You can find it in folder with R1ConnectLibrary.dll

    How to Add the R1 Connect files to Your Project

    Open up your WP project or solution in Visual Studio.

    Select PROJECT -> Add Reference...

    In opened "Reference Manager" window press "Browse"

    Select downloaded libraries R1ConnectLibrary.dll and protobuf-net.dll

    Check Capabilities

    Check your application Capabilities. For it

    Open [Your project]->Properties->WMAppManifest.xml in Solution Explorer.

    Select Capabilities tab

    Check ID_CAP_NETWORKING, ID_CAP_IDENTITY_DEVICE, ID_CAP_LOCATION

    Check ID_CAP_PUSH_NOTIFICATION if you want use R1 Connect Push

    If its turned off, please turn on.

    Using R1Connect SDK Namespace

    You have two ways to execute SDK methods. You can write namespace directly with method, for example:

    Radiumone.Connect.Emitter.Instance.EmitEvent("Your custom event name");

    Or you can add to top of your current .cs file (where the method is invoked)

    using Radiumone.Connect;

    and then simple call SDK methods without namespace prefix:

    Emitter.Instance.EmitEvent("Your custom event name");

    In all examples below used first scheme.

    Setting up your Application

    You will need to initialize the R1 Connect Library in your App.xaml.cs. You can load R1Connect SDK configuration from xml file or configure it in source code.

    Initialize from xml file

    Create xml file and add it to your application project:

    <?xml version="1.0" encoding="utf-8" ?>

    <R1ConnectConfig>

    <ApplicationId>[YOUR APPLICATION ID]</ApplicationId>

    <ClientKey>[YOUR CLIENT KEY]</ClientKey>

    <InProduction>false</InProduction>

    <MPNSServiceName>[YOUR PUSH CHANNEL]</MPNSServiceName>

    <MPNSChannelName>[YOUR SERVICE NAME]</MPNSChannelName>

    <TileAllowedDomains>

    <Domain>[TILES DOMAIN]</Domain>

    </TileAllowedDomains>

    </R1ConnectConfig>

    Start R1 Connect in your application App.xaml.cs

    private void Application_Launching(object sender, LaunchingEventArgs e)

    {

    // Start R1Connect SDK

    var xmlConfig = Radiumone.Connect.Config.LoadFromFile("R1ConnectConfig.xml");

    Radiumone.Connect.SDK.Instance.Start(config);

    }

    Initialize in source code

    Start R1 Connect in your application App.xaml.cs

    private void Application_Launching(object sender, LaunchingEventArgs e)

    {

    // Start R1Connect SDK

    var config = new Radiumone.Connect.Config();

    config.ApplicationId = "[YOUR APPLICATION ID]";

    config.ClientKey = "[YOUR CLIENT KEY]";

    config.MPNSChannelName = "[YOUR PUSH CHANNEL]";

    config.MPNSServiceName = "[YOUR SERVICE NAME]";

    config.TileAllowedDomains.Add(new Uri("[TILES DOMAIN]"));

    #if DEBUG

    config.InProduction = false;

    #else

    config.InProduction = true;

    #endif

    Radiumone.Connect.SDK.Instance.Start(config);

    }

    Push is disabled by default. You can enable it in the Application_Launching method or later.

    Radiumone.Connect.Push.Instance.Enabled = true;

    Emitter & Push Parameters

    The following is a list of configuration parameters for the R1 Connect SDK, most of these contain values that are sent to the tracking server to help identify your app on our platform and to provide analytics on sessions and location.

    Configuration Parameters

    ApplicationUserId

    Optional current user identifier.

    Radiumone.Connect.SDK.Instance.ApplicationUserId = "12345";

    LastCoordinate

    The current user location coordinates. Use it only if your application already uses location services.

    Radiumone.Connect.SDK.Instance.LastCoordinate = ;

    LocationService

    If your application did not use location information before this SDK installation, you can use LocationService in this SDK to enable or disable it:

    Radiumone.Connect.SDK.Instance.LocationService.Enabled = true;

    When enabled, such as in the example above, location information will be sent automatically. However, locationService doesnt fetch the location constantly. For instance, when the location is received the SDK will turn off the location service and wait 10 minutes (by default) before attempting to retrieve it again. You can change this value:

    Radiumone.Connect.SDK.Instance.LocationService.AutoupdateTimeout = 1200; // 20 minutes

    AppVersion

    The application version associated with this emitter. By default, this property is populated with the App Version string from the WMAppManifest.xml. If you wish to override this property, you must do so before making any tracking calls.

    Radiumone.Connect.Emitter.Instance.AppVersion = "1.0.2";

    SessionStart

    If true, indicates the start of a new session. Note that when a emitter is first instantiated, this is initialized to true. To prevent this default behavior, set this to false when the tracker is first obtained.

    By itself, setting this does not send any data. If this is true, when the next emitter call is made, a parameter will be added to the resulting emitter information indicating that it is the start of a session, and this flag will be cleared.

    Radiumone.Connect.Emitter.Instance.SessionStart = true;

    // Your code here

    Radiumone.Connect.Emitter.Instance.SessionStart = false;

    SessionTimeout

    If non-negative, indicates how long, in seconds, the application must transition to the inactive or background state for before the tracker will automatically indicate the start of a new session when the app becomes active again by setting sessionStart to true. For example, if this is set to 30 seconds, and the user receives a phone call that lasts for 45 seconds while using the app, upon returning to the app, the sessionStart parameter will be set to true. If the phone call instead lasted 10 seconds, sessionStart will not be modified.

    To disable automatic session tracking, set this to a negative value. To indicate the start of a session anytime the app becomes inactive or backgrounded, set this to zero.

    By default, this is 30 seconds.

    Radiumone.Connect.Emitter.Instance.SessionTimeout = 15;

    View Article
  • The R1 Connect SDK will automatically capture some generic events, but in order to get the most meaningful data on how users interact with your app the SDK also offers pre-built user-defined events for popular user actions as well as the ability to create your own custom events.

    State Events

    Some events are emitted automatically when the state of the application is changed by the OS and, therefore, they do not require any additional code to be written in the app in order to work out of the box:

    Launch - emitted when the app starts

    First Launch - emitted when the app starts for the first time

    First Launch After Update - emitted when the app starts for the first time after a version upgrade

    Suspend - emitted when the app is put into the background state

    Resume - emitted when the app returns from the background state

    Pre-Defined Events

    Pre-Defined Events are also helpful in measuring certain metrics within the apps and do not require further developer input to function. These particular events below are used to help measure app open events and track Sessions.

    Application Opened - This event is very useful for push notifications and can measure when your app is opened after a message is sent.

    Session Start - As the name implies the Session Start event is used to start a session.

    Session End - The Session End event is used to end a session and passes with it a Session Length attribute that calculates the session length in seconds.

    User-Defined Events

    User-Defined Events are not sent automatically so it is up to you if you want to use them or not. They can provide some great insights on popular user actions if you decide to track them. In order to set this up the application code needs to include the emitter callbacks in order to emit these events.

    Note: The last argument in all of the following emitter methods, otherInfo, is an optional dictionary of key,value pairs or null

    Login

    Tracks a user login within the app

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitLogin("userId", "user_name", otherInfo);

    User Info

    Records an user information

    var userInfo = new Radiumone.Connect.EmitterInfo.UserInfo();

    userInfo.UserID = "userID";

    userInfo.UserName = "userName";

    userInfo.Email = "email";

    userInfo.FirstName = "firstName";

    userInfo.LastName = "lastName";

    userInfo.City = "city";

    userInfo.Phone = "phone";

    userInfo.State = "state";

    userInfo.StreetAddress = "streetAddress";

    userInfo.Zip = "zip";

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitUserInfo(userInfo, otherInfo);

    Registration

    Records a user registration within the app

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitRegistration("userId", "userName", "country", "state", "city", otherInfo);

    Facebook connect

    Allows access to Facebook services

    var socialPermissions = new List<Radiumone.Connect.EmitterInfo.SocialPermission>();

    socialPermissions.Add(new Radiumone.Connect.EmitterInfo.SocialPermission("photos", YES));

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitFBConnect(socialPermissions, otherInfo);

    Twitter connect

    Allows access to Twitter services

    var socialPermissions = new List<Radiumone.Connect.EmitterInfo.SocialPermission>();

    socialPermissions.Add(new Radiumone.Connect.EmitterInfo.SocialPermission("photos", YES));

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitTConnect("12345", "user_name", socialPermissions, otherInfo);

    Upgrade

    Tracks an application version upgrade

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitUpgrade(otherInfo);

    Trial Upgrade

    Tracks an application upgrade from a trial version to a full version

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitTrialUpgrade(otherInfo);

    Screen View

    Basically, a page view, it provides info about that screen

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitScreenView("title",

    "description",

    "http://www.example.com/path",

    "example.com",

    "path",

    otherInfo);

    E-Commerce Events

    Transaction

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitTransaction("transaction_id", "store_id", "store_name", "cart_id", "order_id", 1.5, "USD", 10.5, 12.0, otherInfo);

    TransactionItem

    var lineItem = new Radiumone.Connect.EmitterInfo.LineItem();

    lineItem.ProductID = "product_id";

    lineItem.ProductName = "product_name";

    lineItem.Quantity = 5;

    lineItem.UnitOfMeasure = "unit";

    lineItem.MsrPrice = 10;

    lineItem.PricePaid = 10;

    lineItem.Currency = "USD";

    lineItem.ItemCategory = "category";

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitTransactionItem("transaction_id", lineItem, otherInfo);

    Create Cart

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitCartCreate("cart_id", otherInfo);

    Delete Cart

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitCartDelete("cart_id", otherInfo);

    Add To Cart

    var lineItem = new Radiumone.Connect.EmitterInfo.LineItem();

    lineItem.ProductID = "product_id";

    lineItem.ProductName = "product_name";

    lineItem.Quantity = 5;

    lineItem.UnitOfMeasure = "unit";

    lineItem.MsrPrice = 10;

    lineItem.PricePaid = 10;

    lineItem.Currency = "USD";

    lineItem.ItemCategory = "category";

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitAddToCart("cart_id", lineItem, otherInfo);

    Delete From Cart

    var lineItem = new Radiumone.Connect.EmitterInfo.LineItem();

    lineItem.ProductID = "product_id";

    lineItem.ProductName = "product_name";

    lineItem.Quantity = 5;

    lineItem.UnitOfMeasure = "unit";

    lineItem.MsrPrice = 10;

    lineItem.PricePaid = 10;

    lineItem.Currency = "USD";

    lineItem.ItemCategory = "category";

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitDeleteFromCart("cart_id", lineItem, otherInfo);

    Custom Events

    With custom events you have the ability to create and track specific events that are more closely aligned with your app. If planned and structured correctly, custom events can be strong indicators of user intent and behavior. Some examples include pressing the like button, playing a song, changing the screen mode from portrait to landscape, and zooming in or out of an image. These are all actions by the user that could be tracked with events.

    To include tracking of custom events for the mobile app, the following callbacks need to be included in the application code:

    // Emits a custom event without parameters

    Radiumone.Connect.Emitter.Instance.EmitEvent("Your custom event name");

    Or

    // Emits a custom event with parameters

    var otherInfo = new Dictionary<string, object>();

    otherInfo.Add("custom_key", "value");

    Radiumone.Connect.Emitter.Instance.EmitEvent("Your custom event name", otherInfo);

    View Article
  • Analytics Activation

    i. Automatic Events

    ii. Standard Events

    iii. Custom Events

    iv. In-App Webview Events

    v. Best Practices

    a. Analytics Activation Setup your App Delegate

    (Only for Objective C code)

    #import "R1SDK.h"

    #import "R1Emitter.h"

    #import "R1Push.h"

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    {

    R1SDK *sdk = [R1SDK sharedInstance];

    // Initialize Analytics

    sdk.applicationId = @"YOUR APPLICATION ID"; //Ask your RadiumOne contact for an app id

    // Start SDK

    [sdk start];

    return YES;

    }

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    let sdk = R1SDK.sharedInstance();

    // Initialize Anlaytics

    sdk.applicationId = "YOUR APPLICATION ID";

    // Start SDK

    sdk.start();

    return true

    }

    i. Automatic Events

    The R1 Connect SDK will automatically capture some generic events in order to get the most meaningful data on how users interact with your app. These events are triggered when the state of the application is changed, and therefore do not require any additional code to work out of the box:

    Launch - emitted when the app starts

    First Launch - emitted when the app starts for the first time

    First Launch After Update - emitted when the app starts for the first time after a version upgrade

    Suspend - emitted when the app is put into the background state

    Resume - emitted when the app returns from the background state

    Application Opened - emitted when the app is opened and can measure when your app is opened after a message is sent

    Session Start - emitted when a new session begins

    Session End - emitted when a session ends; includes a Session Length attribute with the session length in seconds.

    ii. Standard Events

    Standard events cover all the main user flows (login, register, share, purchase...) in a standardized format for optimized reporting on the portal, providing a great foundation to your analytics strategy. Once you set them up in your code, they unlock great insights, particularly on user lifetime value.

    Note: The last argument in all of the following emitter callbacks, otherInfo, is a dictionary of key,value pairs or nil, which enables you to customize these events as much as you want.

    Login

    Tracks a user login within the app

    [[R1Emitter sharedInstance] emitLoginWithUserID:@"userId"

    userName:@"user_name"

    otherInfo:@{@"custom_key":@"value"}];

    R1Emitter.sharedInstance()

    .emitLoginWithUserID("userId", userName: "user_name", otherInfo: ["custom_key": "value"]);

    Registration

    Records a user registration within the app

    [[R1Emitter sharedInstance] emitRegistrationWithUserID:@"userId"

    userName:@"userName"

    country:@"country"

    state:@"state"

    city:@"city"

    otherInfo:@{@"custom_key":@"value"}];

    R1Emitter.sharedInstance()

    .emitRegistrationWithUserID("userId", userName: "userName", country: "country", state: "state", city: "city", otherInfo: ["custom_key": "value"]);

    Facebook connect

    Allows access to Facebook services

    NSArray *permissions = @[[R1EmitterSocialPermission socialPermissionWithName:@"photos" granted:YES]];

    [[R1Emitter sharedInstance] emitFBConnectWithPermissions:permissions

    otherInfo:@{@"custom_key":@"value"}];

    let permissions = [R1EmitterSocialPermission.init(name: "photos", granted: true)];

    R1Emitter.sharedInstance()

    .emitFBConnectWithPermissions(permissions, otherInfo: ["custom_key": "value"]);

    Twitter connect

    Allows access to Twitter services

    NSArray *permissions = @[[R1EmitterSocialPermission socialPermissionWithName:@"photos" granted:YES]];

    [[R1Emitter sharedInstance] emitTConnectWithUserID:@"12345"

    userName:@"user_name"

    permissions:permissions

    otherInfo:@{@"custom_key":@"value"}];

    let permissions = [R1EmitterSocialPermission.init(name: "photos", granted: true)];

    R1Emitter.sharedInstance()

    .emitTConnectWithUserID("12345", userName: "user_name", permissions: permissions, otherInfo: ["custom_key": "value"]);

    User Info

    Enables you to send user profiles to the backend.

    R1EmitterUserInfo *userInfo = [R1EmitterUserInfo userInfoWithUserID:@"userId"

    userName:@"userName"

    email:@"[email protected]"

    firstName:@"first name"

    lastName:@"last name"

    streetAddress:@"streetAddress"

    phone:@"phone"

    city:@"city"

    state:@"state"

    zip:@"zip"];

    [[R1Emitter sharedInstance] emitUserInfo:userInfo

    otherInfo:@{@"custom_key":@"value"}];

    let userInfo = R1EmitterUserInfo.init(userID: "userID", userName: "userName", email: "email", firstName: "firstName", lastName: "lastName", streetAddress: "streetAddress", phone: "phone", city: "city", state: "state", zip: "zip");

    R1Emitter.sharedInstance().emitUserInfo(userInfo, otherInfo: ["custom_key": "value"]);

    Upgrade

    Tracks an application version upgrade

    [[R1Emitter sharedInstance] emitUpgradeWithOtherInfo:@{@"custom_key":@"value"}];

    R1Emitter.sharedInstance()

    .emitUpgradeWithOtherInfo(["custom_key": "value"]);

    Trial Upgrade

    Tracks an application upgrade from a trial version to a full version

    [[R1Emitter sharedInstance] emitTrialUpgradeWithOtherInfo:@{@"custom_key":@"value"}];

    R1Emitter.sharedInstance()

    .emitTrialUpgradeWithOtherInfo(["custom_key": "value"]);

    Screen View

    A page view that provides info about that screen

    [[R1Emitter sharedInstance] emitScreenViewWithDocumentTitle:@"title"

    contentDescription:@"description"

    documentLocationUrl:@"http://www.example.com/path"

    documentHostName:@"example.com"

    documentPath:@"path"

    otherInfo:@{@"custom_key":@"value"}];

    R1Emitter.sharedInstance()

    .emitScreenViewWithDocumentTitle("title", contentDescription: "description", documentLocationUrl: "http://www.example.com/path", documentHostName: "example.com", documentPath: "path", otherInfo:["custom_key": "value"]);

    Transaction

    [[R1Emitter sharedInstance] emitTransactionWithID:@"transaction_id"

    storeID:@"store_id"

    storeName:@"store_name"

    cartID:@"cart_id"

    orderID:@"order_id"

    totalSale:1.5

    currency:@"USD"

    shippingCosts:10.5

    transactionTax:12.0

    otherInfo:@{@"custom_key":@"value"}];

    R1Emitter.sharedInstance()

    .emitTransactionWithID("transaction_id", storeID: "store_id", storeName: "store_name", cartID: "cart_id", orderID: "order_id", totalSale: 1.5, currency: "USD", shippingCosts: 10.5, transactionTax: 12.0, otherInfo:["custom_key": "value"]);

    TransactionItem

    R1EmitterLineItem *lineItem = [R1EmitterLineItem itemWithID:@"product_id"

    name:@"product_name"

    quantity:5

    unitOfMeasure:@"unit"

    msrPrice:10

    pricePaid:10

    currency:@"USD"

    itemCategory:@"category"];

    [[R1Emitter sharedInstance] emitTransactionItemWithTransactionID:@"transaction_id"

    lineItem:lineItem

    otherInfo:@{@"custom_key":@"value"}];

    let lineItem = R1EmitterLineItem.init(

    ID: "product_id",

    name: "product_name",

    quantity: 5,

    unitOfMeasure: "unit",

    msrPrice: 10,

    pricePaid: 10,

    currency: "USD",

    itemCategory: "category");

    R1Emitter.sharedInstance()

    .emitTransactionItemWithTransactionID("transaction_id", lineItem: lineItem, otherInfo: ["custom_key": "value"]);

    Create Cart

    [[R1Emitter sharedInstance] emitCartCreateWithCartID:@"cart_id"

    otherInfo:@{@"custom_key":@"value"}];

    R1Emitter.sharedInstance()

    .emitCartCreateWithCartID("cart_id", otherInfo: ["custom_key": "value"]);

    Delete Cart

    [[R1Emitter sharedInstance] emitCartDeleteWithCartID:@"cart_id"

    otherInfo:@{@"custom_key":@"value"}];

    R1Emitter.sharedInstance()

    .emitCartDeleteWithCartID("cart_id", otherInfo: ["custom_key": "value"]);

    Add To Cart

    R1EmitterLineItem *lineItem = [R1EmitterLineItem itemWithID:@"product_id"

    name:@"product_name"

    quantity:5

    unitOfMeasure:@"unit"

    msrPrice:10

    pricePaid:10

    currency:@"USD"

    itemCategory:@"category"];

    [[R1Emitter sharedInstance] emitAddToCartWithCartID:@"cart_id"

    lineItem:lineItem

    otherInfo:@{@"custom_key":@"value"}];

    let lineItem = R1EmitterLineItem.init(

    ID: "product_id",

    name: "product_name",

    quantity: 5,

    unitOfMeasure: "unit",

    msrPrice: 10,

    pricePaid: 10,

    currency: "USD",

    itemCategory: "category");

    R1Emitter.sharedInstance()

    .emitAddToCartWithCartID("cart_id", lineItem: lineItem, otherInfo: ["custom_key": "value"]);

    Delete From Cart

    R1EmitterLineItem *lineItem = [R1EmitterLineItem itemWithID:@"product_id"

    name:@"product_name"

    quantity:5

    unitOfMeasure:@"unit"

    msrPrice:10

    pricePaid:10

    currency:@"USD"

    itemCategory:@"category"];

    [[R1Emitter sharedInstance] emitDeleteFromCartWithCartID:@"cart_id"

    lineItem:lineItem

    otherInfo:@{@"custom_key":@"value"}];

    let lineItem = R1EmitterLineItem.init(

    ID: "product_id",

    name: "product_name",

    quantity: 5,

    unitOfMeasure: "unit",

    msrPrice: 10,

    pricePaid: 10,

    currency: "USD",

    itemCategory: "category");

    R1Emitter.sharedInstance()

    .emitDeleteFromCartWithCartID("cart_id", lineItem: lineItem, otherInfo: ["custom_key": "value"]);

    iii. Custom Events

    Custom events allow you to create and track specific events that are more closely aligned with your app. If planned and structured correctly, custom events can be strong indicators of user intent and behavior. Some examples include pressing the like button, playing a song, changing the screen mode from portrait to landscape, and zooming in or out of an image. These are all actions by the user that could be tracked with events.

    To include tracking of custom events for the mobile app, the following callbacks need to be included in the application code:

    // Emits a custom event without parameters

    [[R1Emitter sharedInstance] emitEvent:@"Your custom event name"];

    // Emits a custom event with parameters

    [[R1Emitter sharedInstance] emitEvent:@"Your custom event name"

    withParameters:@{@"key":@"value"}];

    // Emits a custom event without parameters

    R1Emitter.sharedInstance().emitEvent("Your custom event name");

    // Emits a custom event with parameters

    R1Emitter.sharedInstance().emitEvent("Your custom event name", withParameters: ["key": "value"]);

    iv. In-App Webview Events

    By setting up in-app webview events, you can track events that begin inside your native application but are completed in the embedded browser. To do so, you will have to embed some JavaScript in the page that you will want to fire the event, and you need to properly trigger the webview in your application.

    JavaScript Setup

    To properly fire the event from your webpage, please make the following call:

    R1Connect.emitEvent(eventName,eventParameters);

    For example, both of the following work. The use of parameters is optional.

    R1Connect.emitEvent("Test Event");

    R1Connect.emitEvent("Test Event",{"key":"value"});

    Additionally, please attach the following r1connect.js file to your webpage:

    var R1ConnectBridgePlatforms = {

    UNKNOWN: 0,

    IOS: 1,

    ANDROID: 2

    };

    window.R1Connect = {

    iosBridgeScheme: "r1connectbridge://",

    platform: R1ConnectBridgePlatforms.UNKNOWN,

    iosURLQueue: [],

    iosInProgress: false,

    buildIOSUrl: function(eventName, parameters) {

    var url = this.iosBridgeScheme + 'emit/?event=' + eventName;

    if (parameters)

    url += '&params='+JSON.stringify(parameters);

    return url;

    },

    sendURLInFrame: function(url) {

    var iframe = document.createElement("IFRAME");

    iframe.setAttribute("src", encodeURI(url));

    document.documentElement.appendChild(iframe);

    iframe.parentNode.removeChild(iframe);

    iframe = null;

    },

    emitEvent: function(eventName, parameters) {

    if (this.platform == R1ConnectBridgePlatforms.UNKNOWN) {

    if (window.R1ConnectJSInterface && window.R1ConnectJSInterface.emit)

    this.platform = R1ConnectBridgePlatforms.ANDROID;

    else

    this.platform = R1ConnectBridgePlatforms.IOS;

    }

    if (this.platform == R1ConnectBridgePlatforms.ANDROID) {

    window.R1ConnectJSInterface.emit(eventName, parameters ? JSON.stringify(parameters) : '');

    return;

    }

    var iosURL = this.buildIOSUrl(eventName, parameters);

    if (this.iosInProgress) {

    this.iosURLQueue.push(iosURL);

    return;

    }

    this.iosInProgress = true;

    this.sendURLInFrame(iosURL);

    },

    iosURLReceived: function() {

    setTimeout(function() {

    window.R1Connect._iosURLReceived();

    }, 0);

    },

    _iosURLReceived: function() {

    if (this.iosURLQueue.length == 0) {

    this.iosInProgress = false;

    return;

    }

    var iosURL = this.iosURLQueue.shift();

    this.sendURLInFrame(iosURL);

    },

    };

    To properly handle the events in your application, you first need to import the R1WebViewHelper header file in your ViewController .m implementation file:

    (Only for Objective C code)

    #import "R1WebViewHelper.h"

    You then should setup the UIWebView delegate from the Interface Builder or from code:

    - (void) viewDidLoad {

    [super viewDidLoad];

    self.webView.delegate = self;

    // Your code here

    }

    override func viewDidLoad() {

    super.viewDidLoad();

    webView?.delegate = self;

    // Your code here

    }

    Finally, add the delegate method implementation:

    -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { if (![R1WebViewHelper webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]) return NO; // Your code here return YES; }

    func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {

    if R1WebViewHelper.webView(webView, shouldStartLoadWithRequest: request, navigationType: navigationType) {

    return false;

    }

    // Your code here

    return true;

    }

    v. Best Practices

    Event Naming Convention

    One common mistake is to parametrize event names (with user data for example). Event names should be hard-coded values that you use to segement data on a specific category of event.

    Example: "ProfileViewing"

    Avoid: "Profile Viewing - Lady Gaga's profile"

    As you may have thousands of user profiles in your database, it is preferable to keep the event name high level ("ProfileViewing") so you can run interesting anaytics on it. High level events help answer questions like "how many profiles does a user visit every day on average?"

    Parameter Variance

    Another common mistake is to add parameters to the event that have too many possible values. To follow up on the previous example, one may decide to add the number of profile followers as an event parameter:

    [[R1Emitter sharedInstance] emitEvent:@"ProfileViewing"

    withParameters:@{@"profileFollowers":profileFollowers}];

    R1Emitter.sharedInstance()

    .emitEvent("ProfileViewing", withParameters: ["profileFollowers": profileFollowers]);

    Again, the problem here is that each profile may have any number of followers. This will fragment your data too much to extract any valuable information.

    A good strategy would be to define relevant buckets for high variance parameters. In this case, it might be more relevant to separate traffic on the profiles with a lot of followers from traffic on profiles with very few followers. You could define 3 categories:

    "VERY_INFLUENTIAL" for profiles > 100,000

    "INFLUENTIAL" for profile > 10,000 and <= 100,000

    "NON_INFLUENTIAL" for profile <= 10,000

    A proper event could be

    [[R1Emitter sharedInstance] emitEvent:@"ProfileViewing"

    withParameters:@{@"profileFollowersBucket":@"VERY_INFLUENTIAL"}];

    R1Emitter.sharedInstance()

    .emitEvent("ProfileViewing", withParameters: ["profileFollowersBucket": "VERY_INFLUENTIAL"]);

    This will enable you to create more insightful reports.

    View Article
  • The R1 Connect SDK will automatically capture some generic events, but in order to get the most meaningful data on how users interact with your app the SDK also offers pre-built user-defined events for popular user actions as well as the ability to create your own custom events.

    Automatically tracked events:

    Some events are emitted automatically when the state of the application is changed by the OS and, therefore, they do not require any additional code to be written in the app in order to work out of the box:

    Launch - emitted when the app starts

    First Launch - emitted when the app starts for the first time

    First Launch After Update - emitted when the app starts for the first time after a version upgrade

    Suspend - emitted when the app is put into the background state

    Resume - emitted when the app returns from the background state

    Pre-Defined Events

    Pre-Defined Events are also helpful in measuring certain metrics within the apps and do not require further developer input to function. These particular events below are used to help measure app open events and track Sessions.

    Application Opened - This event is very useful for push notifications and can measure when your app is opened after a message is sent.

    Session Start - As the name implies the Session Start event is used to start a new session.

    Session End - The Session End event is used to end a session and passes with it a Session Length attribute that calculates the session length in seconds.

    User-Defined Events

    User-Defined Events are not sent automatically so it is up to you if you want to use them or not. They can provide some great insights on popular user actions if you decide to track them. In order to set this up the application code needs to include the emitter callbacks in order to emit these events.

    Note: The last argument in all of the following emitter callbacks, otherInfo, is a dictionary of key,value pairs or nil

    User Info

    This event enables you to send user profiles to the backend.

    var userInfo = {"userID":"userId", "userName":"userName", "email":"email",

    "firstName":"firstName", "lastName":"lastName",

    "streetAddress":"streetAddress", "phone":"phone",

    "city":"city", "state":"state", "zip":"zip"};

    R1Emitter.emitUserInfo(userInfo, {"custom_key":"value"});

    Login

    Tracks a user login within the app

    R1Emitter.emitLogin("userId", "user_name", {"custom_key":"value"});

    Registration

    Records a user registration within the app

    R1Emitter.emitRegistration("userId", "userName", "country", "state", "city", {"custom_key":"value"});

    Facebook connect

    Allows access to Facebook services

    R1Emitter.emitFBConnect([{name:"photos", granted:true}], {"custom_key":"value"});

    Twitter connect

    Allows access to Twitter services

    R1Emitter.emitTConnect("12345", "user_name", [{name:"photos", granted:true}], {"custom_key":"value"});

    Upgrade

    Tracks an application version upgrade

    R1Emitter.emitUpgrade({"custom_key":"value"});

    Trial Upgrade

    Tracks an application upgrade from a trial version to a full version

    R1Emitter.emitTrialUpgrade({"custom_key":"value"});

    Screen View

    Basically, a page view, it provides info about that screen

    R1Emitter.emitScreenView("title", "description", "http://www.example.com/path", "example.com", "path", {"custom_key":"value"});

    E-Commerce Events

    Transaction

    R1Emitter.emitTransaction("transaction_id", "store_id", "store_name", "cart_id", "order_id", 1.5, "USD", 10.5, 12.0, {"custom_key":"value"});

    TransactionItem

    var lineItem = {productID:"product_id", productName:"product_name", quantity:5, unitOfMeasure:"unit", msrPrice:10, pricePaid:10, currency:"USD", itemCategory:"category"};

    R1Emitter.emitTransactionItem("transaction_id", lineItem, {"custom_key":"value"});

    Create Cart

    R1Emitter.emitCartCreate("cart_id", {"custom_key":"value"});

    Delete Cart

    R1Emitter.emitCartDelete("cart_id", {"custom_key":"value"});

    Add To Cart

    var lineItem = {productID:"product_id", productName:"product_name", quantity:5, unitOfMeasure:"unit", msrPrice:10, pricePaid:10, currency:"USD", itemCategory:"category"};

    R1Emitter.emitAddToCart("cart_id", lineItem, {"custom_key":"value"});

    Delete From Cart

    var lineItem = {productID:"product_id", productName:"product_name", quantity:5, unitOfMeasure:"unit", msrPrice:10, pricePaid:10, currency:"USD", itemCategory:"category"};

    R1Emitter.emitDeleteFromCart("cart_id", lineItem, {"custom_key":"value"});

    Custom Events

    With custom events you have the ability to create and track specific events that are more closely aligned with your app. If planned and structured correctly, custom events can be strong indicators of user intent and behavior. Some examples include pressing the like button, playing a song, changing the screen mode from portrait to landscape, and zooming in or out of an image. These are all actions by the user that could be tracked with events.

    To include tracking of custom events for the mobile app, the following callbacks need to be included in the application code:

    // Emits a custom event without parameters

    R1Emitter.emitEvent("Your custom event name");

    // Emits a custom event with parameters

    R1Emitter.emitEvent("Your custom event name", {"key":"value"});

    View Article
  • isStarted

    Callback arguments: (bool isStarted)

    Indicates whether the SDK is started. The SDK started automatically if you setted up config.xml.

    R1SDK.isStarted(function (isStarted) {

    //...

    });

    setApplicationUserId

    Set optional current user identifier.

    R1SDK.setApplicationUserId("Your application user id");

    getApplicationUserId

    Callback arguments: (string applicationUserId)

    Get last setted application user identifier.

    R1SDK.getApplicationUserId(function (applicationUserId) {

    //...

    });

    setGeofencingEnabled

    Enable or disable the Geofencing service in the SDK.

    R1SDK.setGeofencingEnabled(true);

    isGeofencingEnabled

    Callback arguments: (bool isGeofencingEnabled)

    Indicates whether Geofencing service is enabled.

    R1SDK.isGeofencingEnabled(function (isGeofencingEnabled) {

    //...

    });

    setEngageEnabled

    Enable or disable the Engage in the SDK.

    R1SDK.setEngageEnabled(true);

    isEngageEnabled

    Callback arguments: (bool isEngageEnabled)

    Indicates whether Engage is enabled.

    R1SDK.isEngageEnabled(function (isEngageEnabled) {

    //...

    });

    R1LocationService

    setEnabled

    Enable or disable the location service for giving location in the SDK.

    R1LocationService.setEnabled(true);

    isEnabled

    Callback arguments: (bool isEnabled)

    Indicates whether R1LocationService is enabled.

    R1LocationService.isEnabled(function (isEnabled) {

    //...

    });

    setAutoupdateTimeout

    When location service is enabled location information will be sent automatically. However, locationService doesnt fetch the location constantly. For instance, when the location is received the SDK will turn off the location in CLLocationManager and wait 10 minutes (by default) before attempting to retrieve it again. You can change this value.

    R1LocationService.setAutoupdateTimeout(1200); // 20 minutes

    getAutoupdateTimeout

    Callback arguments: (float autoupdateTimeout)

    Get currently used autoupdate timeout.

    R1LocationService.getAutoupdateTimeout(function (autoupdateTimeout) {

    //...

    });

    getState

    Callback arguments: (string state)

    Get current state of R1LocationService.

    R1LocationService.getState(function (state) {

    //...

    });

    Possible state values:

    "Disabled"

    "Off"

    "Searching"

    "Has Location"

    "Wait Next Update"

    getCoordinate

    Callback arguments: (object coordinate)

    Get currently used user coordinate.

    R1LocationService.getCoordinate(function (coordinate) {

    if (coordinate == null)

    {

    // Location not received yet

    }else

    {

    // coordinate.latitude

    // coordinate.longitude

    }

    //...

    });

    updateNow

    If R1LocationService is in "Wait Next Update" state, you can update the location manually.

    R1LocationService.updateNow();

    Events

    R1LocationService.state

    Notify the location service state has changed

    document.addEventListener("R1LocationService.state", function(event) {

    // event.state

    }, false);

    R1LocationService.coordinate

    Notify the location service coordinate has changed

    document.addEventListener("R1LocationService.coordinate", function(event) {

    // event.latitude, event.longitude

    }, false);

    R1Emitter

    isStarted

    Callback arguments: (bool isStarted)

    Indicates whether the Emitter has started. The Emitter starts automatically if you set the upcom.radiumone.r1connect.applicationId key in config.xml.

    R1Emitter.isStarted(function (isStarted) {

    //...

    });

    setAppName

    The application name associated with this emitter. By default, this property is populated with the CFBundleName string from the application bundle. If you wish to override this property, you must do so before making any tracking calls.

    R1Emitter.setAppName("Custom application name");

    getAppName

    Callback arguments: (string appName)

    Get last setted application name or CFBundleName by default.

    R1Emitter.getAppName(function (appName) {

    //...

    });

    setAppId

    The application identifier associated with this emitter. If you wish to set this property, you must do so before making any tracking calls. Note: that this is not your app's bundle id, like e.g. com.example.appname.

    R1Emitter.setAppId("12345678");

    getAppId

    Callback arguments: (string appId)

    Get last setted app id.

    R1Emitter.getAppId(function (appId) {

    //...

    });

    setAppVersion

    The application version associated with this emitter. By default, this property is populated with theCFBundleShortVersionString string from the application bundle. If you wish to override this property, you must do so before making any tracking calls.

    R1Emitter.setAppId("12345678");

    getAppVersion

    Callback arguments: (string appVersion)

    Get last setted app version or CFBundleShortVersionString string from the application bundle.

    R1Emitter.getAppVersion(function (appVersion) {

    //...

    });

    setSessionTimeout

    Indicates how long, in seconds, the application must transition to the inactive or background state for before the tracker will automatically indicate the start of a new session when the app becomes active again by setting sessionStart to true. For example, if this is set to 30 seconds, and the user receives a phone call that lasts for 45 seconds while using the app, upon returning to the app, the sessionStart parameter will be set to true. If the phone call instead lasted 10 seconds, sessionStart will not be modified.

    By default, this is 30 seconds.

    R1Emitter.setSessionTimeout(15); // 15 seconds

    getSessionTimeout

    Callback arguments: (float sessionTimeout)

    Get last setted session timeout or default value

    R1Emitter.getSessionTimeout(function (sessionTimeout) {

    //...

    });

    View Article
  • R1Connect PhoneGap/Cordova Plugin

    Platform Support

    This plugin supports PhoneGap/Cordova apps running on iOS, Android and Windows Phone 8.

    Version Requirements

    This plugin is meant to work with PhoneGap 3.x - 4.x. For PhoneGap 5.x+ use branch cordova5

    Installation

    Overview

    This integration doc assumes you have already set up Google Play Services in your application project for android, which is needed to use Google Cloud Messaging (GCM), the notification gateway R1 Connect utilizes. Also you will need to have created the app you will be using in R1 Connect.

    In order to use R1 Connect with your application you will need a project number (sender ID) and API key from Google. Please visit GCM Getting Started here and create a google project and an API key.

    If you do not want to use Push on android you can skip Google Play Services setup (but we recommend not skip this setup);

    Automatic Installation using PhoneGap/Cordova CLI (iOS, Android and WP8)

    Install this plugin using PhoneGap/Cordova cli:

    cordova plugin add https://github.com/radiumone/r1-connect-demo-phonegap

    Modify the www/config.xml ( res/xml/config.xml for android ) directory to contain (replacing with your configuration settings) : Required (for Emitter only):

    If you want to use Push on all platforms:

    <preference name="com.radiumone.r1connect.clientKey" value="Your client Key" />

    If you want to use Push on Android:

    <preference name="com.radiumone.r1connect.senderId" value="Your GCM sender id" />

    If you want to use Push on WP8:

    <preference name="com.radiumone.r1connect.MPNSServiceName" value="[YOUR SERVICE NAME]" />

    <preference name="com.radiumone.r1connect.MPNSChannelName" value="[YOUR PUSH CHANNEL]" />

    <preference name="com.radiumone.r1connect.TileAllowedDomains" value="[TILE DOMAIN 1], [TILE DOMAIN 2]" />

    If you have set up Google Play Services add this line

    <meta-data

    android:name="com.google.android.gms.version"

    android:value="@integer/google_play_services_version" />

    If you want to disable sending all advertising ids to the server add this line

    <preference name="com.radiumone.r1connect.disableAllAdvertisingIds" value="true" />

    iOS manual installation (unnecessary if installed automatically)

    Copy all files from src/ios with subfolders to your project

    Add LibR1Connect.a as a library (Target -> Build Phases -> Link Binary With Libraries)

    Make sure the following frameworks are linked (Target -> Build Phases -> Link Binary With Libraries):

    libsqlite3.dylib

    UIKit.framework

    Foundation.framework

    CoreGraphics.framework

    AdSupport.framework

    CoreTelephony.framework

    CoreLocation.framework

    SystemConfiguration.framework

    Security.framework

    CoreBluetooth.framework

    Modify the cordova config.xml file to include the R1ConnectPlugin and preferences:

    <feature name="R1ConnectPlugin">

    <param name="ios-package" value="R1ConnectPlugin" />

    <param name="onload" value="true" />

    </feature>

    <preference name="com.radiumone.r1connect.applicationId" value="Your application Id" />

    <preference name="com.radiumone.r1connect.clientKey" value="Your client Key (For Push only)" />

    Copy www/R1Connect.js into the project's www directory

    Require the R1Connect module var R1Connect = require('<Path to R1Connect.js>')

    Android manual installation (unnecessary if installed automatically)

    Copy src/Android/R1ConnectPlugin.java and src/Android/CordovaPushReceiver.java files to your projects src/com/radiumone/cordova/plugin/ directory

    Copy src/Android/*.jar files to your projects libs directory

    Copy src/Android/r1connect.properties to your assets directory

    Modify the AndroidManifest.xml to include these permissions:

    <uses-permission android:name="android.permission.INTERNET" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <uses-permission android:name="android.permission.VIBRATE" />

    <uses-permission android:name="android.permission.GET_ACCOUNTS" />

    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    <!-- Please, replace $PACKAGE_NAME with your apps package name-->

    <uses-permission android:name="$PACKAGE_NAME.permission.C2D_MESSAGE" />

    <!-- Please, replace $PACKAGE_NAME with your apps package name-->

    <permission android:name="$PACKAGE_NAME.permission.C2D_MESSAGE" android:protectionLevel="signature" />

    Modify the AndroidManifest.xml Application section to include:

    <receiver android:exported="true" android:name="com.radiumone.emitter.gcm.R1GCMPushReceiver" android:permission="com.google.android.c2dm.permission.SEND">

    <intent-filter>

    <action android:name="com.google.android.c2dm.intent.RECEIVE" />

    <!-- Please, replace $PACKAGE_NAME with your apps package name-->

    <category android:name="$PACKAGE_NAME" />

    </intent-filter>

    </receiver>

    <receiver android:exported="false" android:name="com.radiumone.emitter.push.R1PushBroadcastReceiver">

    <intent-filter>

    <action android:name="com.radiumone.r1push.OPENED_INTERNAL" />

    </intent-filter>

    </receiver>

    <receiver android:exported="false" android:name="com.radiumone.cordova.plugin.CordovaPushReceiver">

    <intent-filter>

    <action android:name="com.radiumone.r1push.OPENED" />

    </intent-filter>

    </receiver>

    <service android:name="com.radiumone.emitter.push.R1ConnectService" />

    <service android:name="com.radiumone.emitter.location.LocationService" />

    If you have set up Google Play Services add this line

    <meta-data

    android:name="com.google.android.gms.version"

    android:value="@integer/google_play_services_version" />

    Modify the cordova config.xml file to include the PushNotificationPlugin:

    <feature name="R1ConnectPlugin">

    <param name="android-package" value="com.radiumone.cordova.plugin.R1ConnectPlugin" />

    <param name="onload" value="true" />

    </feature>

    <preference name="com.radiumone.r1connect.applicationId" value="Your application Id" />

    <preference name="com.radiumone.r1connect.clientKey" value="Your client Key (For Push only)" />

    <preference name="com.radiumone.r1connect.senderId" value="Your google sender id (For Push only)" />

    Copy www/R1Connect.js into the project's www directory

    Require the R1Connect module var R1Connect = require('<Path to R1Connect.js>')

    Windows Phone 8 manual installation (unnecessary if installed automatically)

    Copy all files from src/wp8 with subfolders to your project

    Select PROJECT -> Add Reference...

    In opened "Reference Manager" window press "Browse"

    Select copied libraries R1ConnectLibrary.dll, Newtonsoft.Json.dll and protobuf-net.dll

    Check your application Capabilities. For it

    Open [Your project]->Properties->WMAppManifest.xml in Solution Explorer.

    Select Capabilities tab

    Check ID_CAP_NETWORKING, ID_CAP_IDENTITY_DEVICE, ID_CAP_LOCATION

    Check ID_CAP_PUSH_NOTIFICATION if you want use R1 Connect Push

    Modify the cordova config.xml file to include the R1ConnectPlugin and preferences:

    Copy www/R1Connect.js into the project's www directory

    Require the R1Connect module var R1Connect = require('<Path to R1Connect.js>')

    View Article
  • Attribution Tracking Activation

    We provide attribution tracking for free for all your Android campaigns, whether on or off the R1 DSP, through our partnership with Kochava. The integration is entirely server-side and requires no extra setup or work on your end. This service is a free add-on for our customers.

    If you have another attribution tracking partner that you would prefer to use instead of Kochava, please contact your Account manager and we can work to enable these integrations based on demand from our clients.

    i. Track RadiumOne Campaigns

    Please contact your Account Manager to setup R1 ad campaign as well as tracking campaigns. If you don't have one, please contact us here and one of our Account Managers will assist you.

    Once your Account Manager has set up tracking, you will start receiving attribution tracking report automatically!

    ii. Track 3rd party Campaigns

    Please contact your Account Manager to setup tracking URLs for your 3rd party campaigns. If you don't have one, please contact us here and one of our Account Managers will assist you.

    Send the list of all your media suppliers (anyone you run a mobile advertising campaign with).

    For each media supplier, your account manager will send you 2 tracking URLs (one impression tracking URL, 1 click tracking URL).

    Send each pair of URLs to the relevant Media Supplier so they can set these tracking URLs on the creatives

    You're all set and will start having access to Attribution Tracking Reports

    View Article
  • When preparing to send your binary to Apple, you will set up an application target in the iTunes Connect portal ( http://itunesconnect.apple.com for details). During this process, you will be presented with the question, "Does this app use the Advertising Identifier (IDFA)?"

    Your application may or may not be using this value for your own purposes, but the Connect SDK does access it (described below). So, it is required that you answer, "Yes" to the aforementioned question.

    If your application is utilizing Connect's analytics, geofencing or push notification features, be sure to check the last use case option - that the application uses the IDFA to "Attribute an action taken within this app to a previously served advertisement" as advertisments that you might have served can be related to users actions within your app.

    If your application is also using Connect's Engage (display advertisements) feature, be sure to select the option: "Serve advertisements within the app". Naturally, if your application is only using the Engage functionality, leave all other options unchecked (as related to Connect's use of the IDFA)

    You will also need to confirm that your app honors a user's "Limit Ad Tracking" setting in iOS. The Connect SDK does honor this flag and will not access or otherwise utilize the IDFA value if the user has selected the "Limit Ad Tracking" feature. Ensure that this confirmation and the previously mentioned IDFA use options are checked to facilitate a smooth application review process.

    View Article
  • Attribution Tracking Activation

    We provide attribution tracking for free for all your campaigns, whether on or off the R1 DSP, through our partnership with Kochava. The integration is entirely server-side and requires no extra setup or work on your end. This service is a free add-on for our customers.

    If you have another attribution tracking partner that you would prefer to use instead of Kochava, please contact your Account manager and we can work to enable these integrations based on demand from our clients.

    i. Track RadiumOne Campaigns

    Please contact your Account Manager to setup R1 ad campaign as well as tracking campaigns. If you don't have one, please contact us here and one of our Account Managers will assist you.

    Once your Account Manager has set up tracking, you will start receiving attribution tracking report automatically!

    ii. Track 3rd party Campaigns

    Please contact your Account Manager to setup tracking URLs for your 3rd party campaigns. If you don't have one, please contact us here and one of our Account Managers will assist you.

    Send the list of all your media suppliers (anyone you run a mobile advertising campaign with).

    For each media supplier, your account manager will send you 2 tracking URLs (one impression tracking URL, 1 click tracking URL).

    Send each pair of URLs to the relevant Media Supplier so they can set these tracking URLs on the creatives

    You're all set and will start having access to Attribution Tracking Reports

    View Article
  • We've provided you with the ability to create "Production" and "Development" applications as an easy way to discern between test and production data.

    Nevertheless, these two application types are identical and offer no advantages or disadvantages. While we suggest using "Production" for live data and "Development" for test data, how you use each type of application is entirely up to you.

    View Article
  • If you've just setup Connect for the first time and don't see data on the dashboard after triggering events, don't be alarmed!

    Every night at midnight Eastern time we run a process that aggregates all data for the last 24 hours. This process could take several hours to complete.

    If you don't see any data 24 hours after triggering events, please reach out to us at [email protected].

    View Article
×
Rate your company