Skip to content

Commit

Permalink
Merge pull request #198 from qonversion/release/6.3.0
Browse files Browse the repository at this point in the history
Release 6.3.0
  • Loading branch information
suriksarkisyan committed Jan 16, 2024
2 parents b6c0f99 + 9dccc35 commit ca0a4b8
Show file tree
Hide file tree
Showing 7 changed files with 315 additions and 39 deletions.
4 changes: 2 additions & 2 deletions Editor/QonversionDependencies.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<dependencies>
<androidPackages>
<androidPackage spec="io.qonversion.sandwich:sandwich:3.2.0" />
<androidPackage spec="io.qonversion.sandwich:sandwich:3.3.3" />
<androidPackage spec="com.fasterxml.jackson.core:jackson-databind:2.11.1" />
<androidPackage spec="org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.61" />
</androidPackages>
<iosPods>
<iosPod name="QonversionSandwich" version="3.2.0" />
<iosPod name="QonversionSandwich" version="3.3.3" />
</iosPods>
</dependencies>
75 changes: 44 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
Qonversion
</h1>

Qonversion is the data platform to power in-app subscription revenue growth.
Qonversion - In-app subscription monetization: implement subscriptions and grow your app’s revenue with A/B experiments

* fast in-app subscriptions implementation
* back-end infrastructure to validate user receipts
* manage cross-platform user access to paid content on your app
* comprehensive subscription analytics
* out-of-the-box integrations with the leading marketing, attribution, and product analytics platforms
* push notifications and in-app messaging to win back lapsed subscribers
* A/B Testing for in-app purchases
* In-app subscription management SDK
* API and webhooks to make your subscription data available where you need it
* Seamless Stripe integration to enable cross-platform access management
* Subscribers CRM with user-level transactions
* Instant access to real-time subscription analytics
* Built-in A/B experiments for subscription business model

<p align="center">
<a href="https://qonversion.io"><img width="90%" src="https://qcdn3.sfo3.digitaloceanspaces.com/github/qonversion_platform.png">
Expand All @@ -21,50 +20,65 @@ Qonversion is the data platform to power in-app subscription revenue growth.
[![MIT License](http://img.shields.io/cocoapods/l/Qonversion.svg?style=flat)](https://qonversion.io)


## How It Works: Product Center
## In-App Subscription Implementation & Management

<p align="center">
<a href="https://documentation.qonversion.io/docs/integrations-overview"><img width="90%" src="https://user-images.githubusercontent.com/13959241/161107203-8ef3ecee-86be-47a2-ac57-b21d3da19339.png">
</a>
</p>

1. Application calls the purchase method of Qonversion SDK.
2. Qonversion SDK communicates with StoreKit or Google Billing Client to make a purchase.
3. If a purchase is successful, the SDK sends a request to Qonversion API for server-to-server purchase validation. Qonversion server receives accurate information on the in-app purchase status and user entitlements.
4. SDK returns control to the application with a processing state.
1. Qonversion SDK provides three simple methods to manage subscriptions:
* Get in-app product details
* Make purchases
* Check subscription status to manage premium access
2. Qonversion communicates with Apple or Google platforms both through SDK and server-side to process native in-app payments and keep subscription statuses up to date.
3. You can use Qonversion webhooks and API in addition to SDK to get user-level data where you need it.

See the [quick start guide documentation](https://documentation.qonversion.io/docs/quickstart).

## Analytics

Monitor your in-app revenue metrics. Understand your customers and make better decisions with precise subscription revenue data.
Qonversion provides advanced subscription analytics out-of-the-box. You can monitor real-time metrics from new users and trial-to-paid conversions to revenue, MRR, ARR, cohort retention and more. Understand your customers and make better decisions with precise subscription analytics.

<p align="center">
<a href="https://documentation.qonversion.io/docs/analytics"><img width="90%" src="https://qonversion.io/img/screenshots/desktop/mobile_subscription_analytics.jpg">
<a href="https://documentation.qonversion.io/docs/analytics"><img width="90%" src="https://files.readme.io/9a4fdf6-Analytics.png">
</a>
</p>

## Integrations

Send subscription data to your favorite platforms. Share your mobile and web subscription data using our powerful integrations.
## A/B Experiments

Qonversion's A/B Experiments feature provides everything required to quickly launch paywall and other monetization experiments, analyze results and roll out winning versions without releasing a new app build. Qonversion A/B Experiments include:

* User segmentation by country, install date, app version, free/paying user
* Traffic allocation
* Advanced subscription analytics
* Visualization of A/B experiments results
* Statistical significance of the results
* Roll out winning versions without app release with remote config


<p align="center">
<a href="https://documentation.qonversion.io/docs/integrations-overview"><img width="90%", src="https://qcdn3.sfo3.digitaloceanspaces.com/github/integrations.png">
<a href="https://documentation.qonversion.io/docs/subscription-ab-testing"><img width="90%" src="https://qcdn3.sfo3.digitaloceanspaces.com/github/ab_tests.png">
</a>
</p>

## Personalized push notifications & in-app messaging

Qonversion allows sending automated, personalized push notifications and in-app messages initiated by in-app purchase events. This feature is designed to increase your app's revenue and retention, provide cancellation insights, reduce subscriber churn, and improve your subscribers' user experience.

See more details [here](https://documentation.qonversion.io/docs/paywall-experiments).

See more in the [documentation](https://documentation.qonversion.io/docs/automations)
![](https://qonversion.io/img/@2x/automation/in-app-constructor.gif)
## Integrations

## A/B Testing for in-app purchases
Send user-level subscription data to your favorite platforms.

Boost conversion rates with paywalls and in-app purchases A/B testing. Find the best pricing and paywall variations. Be flexible to prove hypotheses without app releases.
* Amplitude
* Mixpanel
* Appsflyer
* Adjust
* Singular
* CleverTap
* [All other integrations here](qonversion.io/integrations)

<p align="center">
<a href="https://documentation.qonversion.io/docs/subscription-ab-testing"><img width="90%" src="https://user-images.githubusercontent.com/13959241/161716071-b30311b3-b60f-482d-a5d3-c40c1951253b.png">
<a href="https://documentation.qonversion.io/docs/integrations-overview"><img width="90%", src="https://qcdn3.sfo3.digitaloceanspaces.com/github/integrations.png">
</a>
</p>

Expand All @@ -75,18 +89,17 @@ Boost conversion rates with paywalls and in-app purchases A/B testing. Find the
* **Track and increase your revenue.** Qonversion provides detailed real-time revenue analytics including cohort analysis, trial conversion rates, country segmentation, and much more.
* **Integrations with the leading mobile platforms.** Qonversion allows sending data to platforms like AppsFlyer, Adjust, Branch, Tenjin, Facebook Ads, Amplitude, Mixpanel, and many others.
* **Change promoted in-app products.** Change promoted in-app products anytime without app releases.
* **Win back lapsed subscribers.** Qonversion allows sending highly targeted push notifications triggered by server-side subscription events. You can send special offers to users who just canceled a free trial or a subscription. Plus you can deliver in-app messages with a beautiful native design that you create in Qonversion.
* **A/B test** and identify winning in-app purchases, subscriptions or paywals.
* **Cross-device and cross-platform access management.** If you provide user authorization in your app, you can easily set Qonversion to provide premium access to authorized users across devices and operating systems.
* **SDK caches the data.** Qonversion SDK caches purchase data including in-app products and permissions, so the user experience is not affected even with the slow or interrupting network connection.
* **SDK caches the data.** Qonversion SDK caches purchase data including in-app products and entitlements, so the user experience is not affected even with the slow or interrupting network connection.
* **Webhooks.** You can easily send all of the data to your server with Qonversion webhooks.
* **Customer support.** You can always reach out to our customer support and get the help required.

Convinced? Let's go!

## Documentation

Check the [documentation](https://documentation.qonversion.io/docs/quickstart) to learn details on implementing and using Qonversion SDKs.
Check the [full documentation](https://documentation.qonversion.io/docs/quickstart) to learn about implementation details and available features.

#### Help us improve the documentation

Expand All @@ -113,4 +126,4 @@ Contact us via [issues on GitHub](https://github.com/qonversion/unity-sdk/issues

## License

Qonversion SDK is available under the MIT license.
Qonversion SDK is available under the MIT license.
91 changes: 87 additions & 4 deletions Runtime/Scripts/Dto/Entitlement.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using JetBrains.Annotations;

namespace QonversionUnity
{
Expand All @@ -19,7 +20,7 @@ public class Entitlement

/// A source determining where this entitlement is originally from - App Store, Play Store, Stripe, etc.
public readonly QEntitlementSource Source;

/// Purchase date
public readonly DateTime StartedDate;

Expand All @@ -31,6 +32,32 @@ public class Entitlement
/// Subscription could be canceled, but the user could still have a entitlement
public readonly bool IsActive;

/// Renews count for the entitlement. Renews count starts from the second paid subscription.
/// For example, we have 20 transactions.One is the trial, and one is the first paid transaction after the trial.
/// Renews count is equal to 18.
public readonly int RenewsCount;

/// Trial start date.
public readonly DateTime? TrialStartDate;

/// First purchase date.
public readonly DateTime? FirstPurchaseDate;

/// Last purchase date.
public readonly DateTime? LastPurchaseDate;

/// Last activated offer code.
[CanBeNull] public readonly string LastActivatedOfferCode;

/// Grant type of the entitlement.
public readonly QEntitlementGrantType GrantType;

/// Auto-renew disable date.
public readonly DateTime? AutoRenewDisableDate;

/// Array of the transactions that unlocked current entitlement.
public readonly List<Transaction> Transactions;

public Entitlement(Dictionary<string, object> dict)
{
if (dict.TryGetValue("id", out object value)) Id = value as string;
Expand All @@ -40,6 +67,20 @@ public Entitlement(Dictionary<string, object> dict)
if (dict.TryGetValue("active", out value)) IsActive = (bool)value;
if (dict.TryGetValue("startedTimestamp", out value)) StartedDate = FormatDate(value);
if (dict.TryGetValue("expirationTimestamp", out value) && value != null) ExpirationDate = FormatDate(value);
if (dict.TryGetValue("trialStartTimestamp", out value) && value != null) TrialStartDate = FormatDate(value);
if (dict.TryGetValue("firstPurchaseTimestamp", out value) && value != null) FirstPurchaseDate = FormatDate(value);
if (dict.TryGetValue("lastPurchaseTimestamp", out value) && value != null) LastPurchaseDate = FormatDate(value);
if (dict.TryGetValue("autoRenewDisableTimestamp", out value) && value != null) AutoRenewDisableDate = FormatDate(value);
if (dict.TryGetValue("lastActivatedOfferCode", out value)) LastActivatedOfferCode = value as string;

GrantType = dict.TryGetValue("grantType", out value) ? FormatGrantType(value) : QEntitlementGrantType.Purchase;

if (dict.TryGetValue("transactions", out value) && value is List<object> transactions)
{
Transactions = Mapper.ConvertObjectsList<Transaction>(transactions);
}

RenewsCount = dict.TryGetValue("renewsCount", out value) ? (int)(long)value : 0;
}

public override string ToString()
Expand All @@ -50,17 +91,25 @@ public override string ToString()
$"{nameof(Source)}: {Source}, " +
$"{nameof(StartedDate)}: {StartedDate}, " +
$"{nameof(ExpirationDate)}: {ExpirationDate}, " +
$"{nameof(IsActive)}: {IsActive}";
$"{nameof(IsActive)}: {IsActive}, " +
$"{nameof(RenewsCount)}: {RenewsCount}, " +
$"{nameof(TrialStartDate)}: {TrialStartDate}, " +
$"{nameof(FirstPurchaseDate)}: {FirstPurchaseDate}, " +
$"{nameof(LastPurchaseDate)}: {LastPurchaseDate}, " +
$"{nameof(LastActivatedOfferCode)}: {LastActivatedOfferCode}, " +
$"{nameof(GrantType)}: {GrantType}, " +
$"{nameof(AutoRenewDisableDate)}: {AutoRenewDisableDate}, " +
$"{nameof(Transactions)}: {Utils.PrintObjectList(Transactions)}";
}

private DateTime FormatDate(object time)
{
if (time is double)
{
return Utils.FormatDate(Convert.ToInt64((double)time));
}
}

return Utils.FormatDate((long) time);
return Utils.FormatDate((long)time);
}

private QEntitlementRenewState FormatRenewState(object renewState)
Expand Down Expand Up @@ -95,6 +144,32 @@ private QEntitlementSource FormatEntitlementSource(object source)
? parsedSource
: QEntitlementSource.Unknown;
}

private QEntitlementGrantType FormatGrantType(object grantType)
{
string value = grantType as string;
QEntitlementGrantType result;
switch (value)
{
case "Purchase":
result = QEntitlementGrantType.Purchase;
break;
case "FamilySharing":
result = QEntitlementGrantType.FamilySharing;
break;
case "OfferCode":
result = QEntitlementGrantType.OfferCode;
break;
case "Manual":
result = QEntitlementGrantType.Manual;
break;
default:
result = QEntitlementGrantType.Purchase;
break;
}

return result;
}
}

public enum QEntitlementRenewState
Expand All @@ -121,4 +196,12 @@ public enum QEntitlementSource
Stripe,
Manual
}

public enum QEntitlementGrantType
{
Purchase,
FamilySharing,
OfferCode,
Manual
}
}
Loading

0 comments on commit ca0a4b8

Please sign in to comment.