Summary
During the annual I/O conference, Google introduced its new major version of the Google Play Billing Library. Besides classic method deprecations and removals, there was also vast information about the new architecture of subscriptions, which aims to simplify the way you can create, manage and sell in-app purchases. In this article, I will explore the updates to Google Play Billing Library 5.0 and dig deeper into the most interesting ones.
The New Subscription Model
Purchasing New Subscriptions
Speaking of code, in Google Play Billing Library 5.0, the SkuDetails
class is deprecated as well as every other entity or method containing Sku
in its name. Now you should consider using ProductDetails
for that purpose. Product details contain information about a subscription, including its base plans and offers.
Before, you requested subscription details like those below:
val params = SkuDetailsParams.newBuilder() .setType(BillingClient.SkuType.SUBS) .setSkusList(listOf("premium")) .build() billingClient.querySkuDetailsAsync(params) { billingResult, skuDetailsList -> // Process the result }
Copy
Now, you should do the following:
val productList = listOf( QueryProductDetailsParams.Product.newBuilder() .setProductType(BillingClient.SkuType.SUBS) .setProductId("premium") .build() ) val params = QueryProductDetailsParams.newBuilder() .setProductList(productList) .build() billingClient.queryProductDetailsAsync(params) { billingResult, productDetailsList -> // Process the result }
Copy
And, for launching the purchase flow, you used the following constructions:
val billingFlowParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build() val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Copy
Whereas now they should look like those that follow:
// Note that `subscriptionOfferDetails` can be null if it is an in-app product, not a subscription. val offerToken = productDetails.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken ?: return val productDetailsParamsList = listOf( BillingFlowParams.ProductDetailsParams.newBuilder() .setProductDetails(productDetails) .setOfferToken(offerToken) .build() ) val billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Copy
You can also look at the migration examples in the Google official migration steps. Note, that there are a few typos in their examples which are fixed here.
Let’s overview the changes.
As I mentioned, you should now use ProductDetails
for querying subscription details and purchasing flow. In addition, you should provide an offerToken
to billing flow params as each ProductDetails
may contain several offers. Note, that the offer details array (productDetails.subscriptionOfferDetails
) always contains base plan details (if any base plan exists), so even if your subscription contains only a base plan without offers it will still have offerToken
for purchase.
You could notice that the new purchase flow accepts multiple ProductDetails
instead of one SkuDetails
like in the previous version. But if you provide more than one ProductDetails
, the flow will end up with an error. The official integration guide gives the wrong example of using the setProductDetails
and setOfferToken
methods right on the BillingFlowParams.Builder
class, but there is only the setProductDetailsParamsList
method available for those purposes. It seems as if Google decided to switch from single product details to multiple quite recently with a vision for the future when Billing will support multiple different subscription purchases at once.
The rest flow — namely processing the purchase — remains the same as in the Google Play Billing Library 4.0.
Subscriptions Backward Compatibility
Well, everything sounds good so far, but what if you don’t want to migrate right now? Google has taken care of it.
Despite Google Play Console already working only with the new subscription model, all the old subscriptions are converted to the new format automatically, saving their backward compatibility. This means that you see your subscriptions in the new format on Google Console but can still work with them as you did before on your app.
You will also notice that all the old subscriptions are made read-only after migration. Google warns you that editing will disable InAppProducts API support for that subscription.
You might be using this API in your backend for fetching some product details, so be careful — after making the subscription editable you will receive errors (as shown below) from that API if you try to fetch converted subscription info. The same will happen to all new subscriptions created after May, 11th.
HTTP code - 422 Non-existent in-app product: com.qonversion.sample\/ProductId{productId=article_test_trial}
Copy
So, if you use InAppProducts API, consider upgrading it before creating new subscriptions or editing old ones.
While surfing through the new subscriptions UI in Google Play Console, you will find “Backwards compatible” tags near base plans and offers of subscriptions. This means that if you purchase those subscriptions using deprecated SkuDetails
(as you do in Google Play Billing Library 4.0), you will buy exactly those compatible base plans/offers. If there is only a compatible base plan, without any compatible offer, then that base plan will be purchased. If there are both compatible base plan and offer available then if the offer is eligible to the current user, it will be purchased, else — base plan. You can choose another base plan/offer as backward compatible if you would like.
Note — this Backwards compatibility relates to Google Play Billing Library but not to InAppProducts API. As mentioned, if you begin using new features, for example, multiple base plans or offers for one subscription or just convert it from read-only to editable, that subscription can still be Backwards compatible for an app, but not for API.
The Other Updates
There were several minor updates in the Google Play Billing Library 5.0 which are worth briefly mentioning.
The method
queryPurchases
deprecated in Google Play Billing Library 4.0 was removedNo more synchronized requests, only
queryPurchasesAsync
.launchPriceChangeFlow
has been deprecated — the new recommended price change flow requires clients’ confirmation via the Google Play subscriptions page, so you should use deep links for navigation there instead of calling theBillingClient
method.Added the
setIsOfferPersonalized
method to indicate a personalized price for EU clients following the Consumer Rights Directive. This option adds a line to the bottom of the Google Billing purchase screen noting that a price is personalized.
The New Subscription Model and Qonversion
While we are working on Google Play Billing Library 5.0 support, you can still use Qonversion SDK for your in-app purchases. We are now using Google Play Billing Library 4.0, which means we can manage only subscriptions with backward-compatible base plans and offers. You are still able to edit properties that were available in the previous subscriptions model like a price, grace period, trial duration, and so on as well as create new subscriptions. Just be sure that after you still have at least one backward compatible base plan and, if needed, a backward-compatible offer. And, we still require a whole subscription identifier for configuring products on our Product Center, not base plan or offer identifiers.
If you have any questions, please let us know. We will be happy to assist you.
During the annual I/O conference, Google introduced its new major version of the Google Play Billing Library. Besides classic method deprecations and removals, there was also vast information about the new architecture of subscriptions, which aims to simplify the way you can create, manage and sell in-app purchases. In this article, I will explore the updates to Google Play Billing Library 5.0 and dig deeper into the most interesting ones.
The New Subscription Model
Purchasing New Subscriptions
Speaking of code, in Google Play Billing Library 5.0, the SkuDetails
class is deprecated as well as every other entity or method containing Sku
in its name. Now you should consider using ProductDetails
for that purpose. Product details contain information about a subscription, including its base plans and offers.
Before, you requested subscription details like those below:
val params = SkuDetailsParams.newBuilder() .setType(BillingClient.SkuType.SUBS) .setSkusList(listOf("premium")) .build() billingClient.querySkuDetailsAsync(params) { billingResult, skuDetailsList -> // Process the result }
Copy
Now, you should do the following:
val productList = listOf( QueryProductDetailsParams.Product.newBuilder() .setProductType(BillingClient.SkuType.SUBS) .setProductId("premium") .build() ) val params = QueryProductDetailsParams.newBuilder() .setProductList(productList) .build() billingClient.queryProductDetailsAsync(params) { billingResult, productDetailsList -> // Process the result }
Copy
And, for launching the purchase flow, you used the following constructions:
val billingFlowParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build() val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Copy
Whereas now they should look like those that follow:
// Note that `subscriptionOfferDetails` can be null if it is an in-app product, not a subscription. val offerToken = productDetails.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken ?: return val productDetailsParamsList = listOf( BillingFlowParams.ProductDetailsParams.newBuilder() .setProductDetails(productDetails) .setOfferToken(offerToken) .build() ) val billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Copy
You can also look at the migration examples in the Google official migration steps. Note, that there are a few typos in their examples which are fixed here.
Let’s overview the changes.
As I mentioned, you should now use ProductDetails
for querying subscription details and purchasing flow. In addition, you should provide an offerToken
to billing flow params as each ProductDetails
may contain several offers. Note, that the offer details array (productDetails.subscriptionOfferDetails
) always contains base plan details (if any base plan exists), so even if your subscription contains only a base plan without offers it will still have offerToken
for purchase.
You could notice that the new purchase flow accepts multiple ProductDetails
instead of one SkuDetails
like in the previous version. But if you provide more than one ProductDetails
, the flow will end up with an error. The official integration guide gives the wrong example of using the setProductDetails
and setOfferToken
methods right on the BillingFlowParams.Builder
class, but there is only the setProductDetailsParamsList
method available for those purposes. It seems as if Google decided to switch from single product details to multiple quite recently with a vision for the future when Billing will support multiple different subscription purchases at once.
The rest flow — namely processing the purchase — remains the same as in the Google Play Billing Library 4.0.
Subscriptions Backward Compatibility
Well, everything sounds good so far, but what if you don’t want to migrate right now? Google has taken care of it.
Despite Google Play Console already working only with the new subscription model, all the old subscriptions are converted to the new format automatically, saving their backward compatibility. This means that you see your subscriptions in the new format on Google Console but can still work with them as you did before on your app.
You will also notice that all the old subscriptions are made read-only after migration. Google warns you that editing will disable InAppProducts API support for that subscription.
You might be using this API in your backend for fetching some product details, so be careful — after making the subscription editable you will receive errors (as shown below) from that API if you try to fetch converted subscription info. The same will happen to all new subscriptions created after May, 11th.
HTTP code - 422 Non-existent in-app product: com.qonversion.sample\/ProductId{productId=article_test_trial}
Copy
So, if you use InAppProducts API, consider upgrading it before creating new subscriptions or editing old ones.
While surfing through the new subscriptions UI in Google Play Console, you will find “Backwards compatible” tags near base plans and offers of subscriptions. This means that if you purchase those subscriptions using deprecated SkuDetails
(as you do in Google Play Billing Library 4.0), you will buy exactly those compatible base plans/offers. If there is only a compatible base plan, without any compatible offer, then that base plan will be purchased. If there are both compatible base plan and offer available then if the offer is eligible to the current user, it will be purchased, else — base plan. You can choose another base plan/offer as backward compatible if you would like.
Note — this Backwards compatibility relates to Google Play Billing Library but not to InAppProducts API. As mentioned, if you begin using new features, for example, multiple base plans or offers for one subscription or just convert it from read-only to editable, that subscription can still be Backwards compatible for an app, but not for API.
The Other Updates
There were several minor updates in the Google Play Billing Library 5.0 which are worth briefly mentioning.
The method
queryPurchases
deprecated in Google Play Billing Library 4.0 was removedNo more synchronized requests, only
queryPurchasesAsync
.launchPriceChangeFlow
has been deprecated — the new recommended price change flow requires clients’ confirmation via the Google Play subscriptions page, so you should use deep links for navigation there instead of calling theBillingClient
method.Added the
setIsOfferPersonalized
method to indicate a personalized price for EU clients following the Consumer Rights Directive. This option adds a line to the bottom of the Google Billing purchase screen noting that a price is personalized.
The New Subscription Model and Qonversion
While we are working on Google Play Billing Library 5.0 support, you can still use Qonversion SDK for your in-app purchases. We are now using Google Play Billing Library 4.0, which means we can manage only subscriptions with backward-compatible base plans and offers. You are still able to edit properties that were available in the previous subscriptions model like a price, grace period, trial duration, and so on as well as create new subscriptions. Just be sure that after you still have at least one backward compatible base plan and, if needed, a backward-compatible offer. And, we still require a whole subscription identifier for configuring products on our Product Center, not base plan or offer identifiers.
If you have any questions, please let us know. We will be happy to assist you.
During the annual I/O conference, Google introduced its new major version of the Google Play Billing Library. Besides classic method deprecations and removals, there was also vast information about the new architecture of subscriptions, which aims to simplify the way you can create, manage and sell in-app purchases. In this article, I will explore the updates to Google Play Billing Library 5.0 and dig deeper into the most interesting ones.
The New Subscription Model
Purchasing New Subscriptions
Speaking of code, in Google Play Billing Library 5.0, the SkuDetails
class is deprecated as well as every other entity or method containing Sku
in its name. Now you should consider using ProductDetails
for that purpose. Product details contain information about a subscription, including its base plans and offers.
Before, you requested subscription details like those below:
val params = SkuDetailsParams.newBuilder() .setType(BillingClient.SkuType.SUBS) .setSkusList(listOf("premium")) .build() billingClient.querySkuDetailsAsync(params) { billingResult, skuDetailsList -> // Process the result }
Copy
Now, you should do the following:
val productList = listOf( QueryProductDetailsParams.Product.newBuilder() .setProductType(BillingClient.SkuType.SUBS) .setProductId("premium") .build() ) val params = QueryProductDetailsParams.newBuilder() .setProductList(productList) .build() billingClient.queryProductDetailsAsync(params) { billingResult, productDetailsList -> // Process the result }
Copy
And, for launching the purchase flow, you used the following constructions:
val billingFlowParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build() val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Copy
Whereas now they should look like those that follow:
// Note that `subscriptionOfferDetails` can be null if it is an in-app product, not a subscription. val offerToken = productDetails.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken ?: return val productDetailsParamsList = listOf( BillingFlowParams.ProductDetailsParams.newBuilder() .setProductDetails(productDetails) .setOfferToken(offerToken) .build() ) val billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Copy
You can also look at the migration examples in the Google official migration steps. Note, that there are a few typos in their examples which are fixed here.
Let’s overview the changes.
As I mentioned, you should now use ProductDetails
for querying subscription details and purchasing flow. In addition, you should provide an offerToken
to billing flow params as each ProductDetails
may contain several offers. Note, that the offer details array (productDetails.subscriptionOfferDetails
) always contains base plan details (if any base plan exists), so even if your subscription contains only a base plan without offers it will still have offerToken
for purchase.
You could notice that the new purchase flow accepts multiple ProductDetails
instead of one SkuDetails
like in the previous version. But if you provide more than one ProductDetails
, the flow will end up with an error. The official integration guide gives the wrong example of using the setProductDetails
and setOfferToken
methods right on the BillingFlowParams.Builder
class, but there is only the setProductDetailsParamsList
method available for those purposes. It seems as if Google decided to switch from single product details to multiple quite recently with a vision for the future when Billing will support multiple different subscription purchases at once.
The rest flow — namely processing the purchase — remains the same as in the Google Play Billing Library 4.0.
Subscriptions Backward Compatibility
Well, everything sounds good so far, but what if you don’t want to migrate right now? Google has taken care of it.
Despite Google Play Console already working only with the new subscription model, all the old subscriptions are converted to the new format automatically, saving their backward compatibility. This means that you see your subscriptions in the new format on Google Console but can still work with them as you did before on your app.
You will also notice that all the old subscriptions are made read-only after migration. Google warns you that editing will disable InAppProducts API support for that subscription.
You might be using this API in your backend for fetching some product details, so be careful — after making the subscription editable you will receive errors (as shown below) from that API if you try to fetch converted subscription info. The same will happen to all new subscriptions created after May, 11th.
HTTP code - 422 Non-existent in-app product: com.qonversion.sample\/ProductId{productId=article_test_trial}
Copy
So, if you use InAppProducts API, consider upgrading it before creating new subscriptions or editing old ones.
While surfing through the new subscriptions UI in Google Play Console, you will find “Backwards compatible” tags near base plans and offers of subscriptions. This means that if you purchase those subscriptions using deprecated SkuDetails
(as you do in Google Play Billing Library 4.0), you will buy exactly those compatible base plans/offers. If there is only a compatible base plan, without any compatible offer, then that base plan will be purchased. If there are both compatible base plan and offer available then if the offer is eligible to the current user, it will be purchased, else — base plan. You can choose another base plan/offer as backward compatible if you would like.
Note — this Backwards compatibility relates to Google Play Billing Library but not to InAppProducts API. As mentioned, if you begin using new features, for example, multiple base plans or offers for one subscription or just convert it from read-only to editable, that subscription can still be Backwards compatible for an app, but not for API.
The Other Updates
There were several minor updates in the Google Play Billing Library 5.0 which are worth briefly mentioning.
The method
queryPurchases
deprecated in Google Play Billing Library 4.0 was removedNo more synchronized requests, only
queryPurchasesAsync
.launchPriceChangeFlow
has been deprecated — the new recommended price change flow requires clients’ confirmation via the Google Play subscriptions page, so you should use deep links for navigation there instead of calling theBillingClient
method.Added the
setIsOfferPersonalized
method to indicate a personalized price for EU clients following the Consumer Rights Directive. This option adds a line to the bottom of the Google Billing purchase screen noting that a price is personalized.
The New Subscription Model and Qonversion
While we are working on Google Play Billing Library 5.0 support, you can still use Qonversion SDK for your in-app purchases. We are now using Google Play Billing Library 4.0, which means we can manage only subscriptions with backward-compatible base plans and offers. You are still able to edit properties that were available in the previous subscriptions model like a price, grace period, trial duration, and so on as well as create new subscriptions. Just be sure that after you still have at least one backward compatible base plan and, if needed, a backward-compatible offer. And, we still require a whole subscription identifier for configuring products on our Product Center, not base plan or offer identifiers.
If you have any questions, please let us know. We will be happy to assist you.
During the annual I/O conference, Google introduced its new major version of the Google Play Billing Library. Besides classic method deprecations and removals, there was also vast information about the new architecture of subscriptions, which aims to simplify the way you can create, manage and sell in-app purchases. In this article, I will explore the updates to Google Play Billing Library 5.0 and dig deeper into the most interesting ones.
The New Subscription Model
Purchasing New Subscriptions
Speaking of code, in Google Play Billing Library 5.0, the SkuDetails
class is deprecated as well as every other entity or method containing Sku
in its name. Now you should consider using ProductDetails
for that purpose. Product details contain information about a subscription, including its base plans and offers.
Before, you requested subscription details like those below:
val params = SkuDetailsParams.newBuilder() .setType(BillingClient.SkuType.SUBS) .setSkusList(listOf("premium")) .build() billingClient.querySkuDetailsAsync(params) { billingResult, skuDetailsList -> // Process the result }
Copy
Now, you should do the following:
val productList = listOf( QueryProductDetailsParams.Product.newBuilder() .setProductType(BillingClient.SkuType.SUBS) .setProductId("premium") .build() ) val params = QueryProductDetailsParams.newBuilder() .setProductList(productList) .build() billingClient.queryProductDetailsAsync(params) { billingResult, productDetailsList -> // Process the result }
Copy
And, for launching the purchase flow, you used the following constructions:
val billingFlowParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build() val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Copy
Whereas now they should look like those that follow:
// Note that `subscriptionOfferDetails` can be null if it is an in-app product, not a subscription. val offerToken = productDetails.subscriptionOfferDetails?.get(selectedOfferIndex)?.offerToken ?: return val productDetailsParamsList = listOf( BillingFlowParams.ProductDetailsParams.newBuilder() .setProductDetails(productDetails) .setOfferToken(offerToken) .build() ) val billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Copy
You can also look at the migration examples in the Google official migration steps. Note, that there are a few typos in their examples which are fixed here.
Let’s overview the changes.
As I mentioned, you should now use ProductDetails
for querying subscription details and purchasing flow. In addition, you should provide an offerToken
to billing flow params as each ProductDetails
may contain several offers. Note, that the offer details array (productDetails.subscriptionOfferDetails
) always contains base plan details (if any base plan exists), so even if your subscription contains only a base plan without offers it will still have offerToken
for purchase.
You could notice that the new purchase flow accepts multiple ProductDetails
instead of one SkuDetails
like in the previous version. But if you provide more than one ProductDetails
, the flow will end up with an error. The official integration guide gives the wrong example of using the setProductDetails
and setOfferToken
methods right on the BillingFlowParams.Builder
class, but there is only the setProductDetailsParamsList
method available for those purposes. It seems as if Google decided to switch from single product details to multiple quite recently with a vision for the future when Billing will support multiple different subscription purchases at once.
The rest flow — namely processing the purchase — remains the same as in the Google Play Billing Library 4.0.
Subscriptions Backward Compatibility
Well, everything sounds good so far, but what if you don’t want to migrate right now? Google has taken care of it.
Despite Google Play Console already working only with the new subscription model, all the old subscriptions are converted to the new format automatically, saving their backward compatibility. This means that you see your subscriptions in the new format on Google Console but can still work with them as you did before on your app.
You will also notice that all the old subscriptions are made read-only after migration. Google warns you that editing will disable InAppProducts API support for that subscription.
You might be using this API in your backend for fetching some product details, so be careful — after making the subscription editable you will receive errors (as shown below) from that API if you try to fetch converted subscription info. The same will happen to all new subscriptions created after May, 11th.
HTTP code - 422 Non-existent in-app product: com.qonversion.sample\/ProductId{productId=article_test_trial}
Copy
So, if you use InAppProducts API, consider upgrading it before creating new subscriptions or editing old ones.
While surfing through the new subscriptions UI in Google Play Console, you will find “Backwards compatible” tags near base plans and offers of subscriptions. This means that if you purchase those subscriptions using deprecated SkuDetails
(as you do in Google Play Billing Library 4.0), you will buy exactly those compatible base plans/offers. If there is only a compatible base plan, without any compatible offer, then that base plan will be purchased. If there are both compatible base plan and offer available then if the offer is eligible to the current user, it will be purchased, else — base plan. You can choose another base plan/offer as backward compatible if you would like.
Note — this Backwards compatibility relates to Google Play Billing Library but not to InAppProducts API. As mentioned, if you begin using new features, for example, multiple base plans or offers for one subscription or just convert it from read-only to editable, that subscription can still be Backwards compatible for an app, but not for API.
The Other Updates
There were several minor updates in the Google Play Billing Library 5.0 which are worth briefly mentioning.
The method
queryPurchases
deprecated in Google Play Billing Library 4.0 was removedNo more synchronized requests, only
queryPurchasesAsync
.launchPriceChangeFlow
has been deprecated — the new recommended price change flow requires clients’ confirmation via the Google Play subscriptions page, so you should use deep links for navigation there instead of calling theBillingClient
method.Added the
setIsOfferPersonalized
method to indicate a personalized price for EU clients following the Consumer Rights Directive. This option adds a line to the bottom of the Google Billing purchase screen noting that a price is personalized.
The New Subscription Model and Qonversion
While we are working on Google Play Billing Library 5.0 support, you can still use Qonversion SDK for your in-app purchases. We are now using Google Play Billing Library 4.0, which means we can manage only subscriptions with backward-compatible base plans and offers. You are still able to edit properties that were available in the previous subscriptions model like a price, grace period, trial duration, and so on as well as create new subscriptions. Just be sure that after you still have at least one backward compatible base plan and, if needed, a backward-compatible offer. And, we still require a whole subscription identifier for configuring products on our Product Center, not base plan or offer identifiers.
If you have any questions, please let us know. We will be happy to assist you.
Start Now for Free
Or book a demo with our team to learn more about Qonversion
Start Now for Free
Or book a demo with our team to learn more about Qonversion
Start Now for Free
Or book a demo with our team to learn more about Qonversion
Read more
Read more
Trash Panda Maximizes App Revenue after Setting the Best Subscription Price with A/B Tests
Jul 8, 2024
Jul 8, 2024
How StyleDNA Saved 20% Development Time and Unlocked New Features
Jun 19, 2024
Jun 19, 2024
WWDC24 Updates for App Developers | What's new in Storekit 2 and App Store Server API?
Jun 17, 2024
Jun 17, 2024
How A/B Testing with Qonversion Helped Iben Sandahl’s Parenting App Double Their Sales
Jun 13, 2024
Jun 13, 2024
Trash Panda Maximizes App Revenue after Setting the Best Subscription Price with A/B Tests
Jul 8, 2024
Jul 8, 2024
How StyleDNA Saved 20% Development Time and Unlocked New Features
Jun 19, 2024
Jun 19, 2024
WWDC24 Updates for App Developers | What's new in Storekit 2 and App Store Server API?
Jun 17, 2024
Jun 17, 2024