My App does not actively prompt the user to rate the app on the App Store, it only includes a "Rate this app" page in the app settings. So the user has access the page manually and only after he taps on a Do Rate button, he is redirected to the App Store.
Of course the UI of SKStoreReviewController is much more straight forward than redirecting the user to the App Store app to leave his review. So I simply changed the call to the App Store URL to a call of [SKStoreReviewController requestReview].
This works fine in all my tests: The rating dialog is presented every time I tap the review button.
However I wonder how this will behave outside the debug environment in real live. According to the Apple docs, [SKStoreReviewController requestReview] is limited to 3 prompts per App per year.
How will the app behave once this limit is reached? Will pressing the review-button (= [SKStoreReviewController requestReview]) have no effect or will there be some kind of feedback?
How do I know if I can sill use [SKStoreReviewController requestReview] or if I have to send the user to the Store manually?
What exactly does 3 prompts per App per year mean? Is this really per App or per App Version?
Is there any limitation to the interval between two [SKStoreReviewController requestReview] calls? Is using it three days in a row as legit as using it every 4 month?
Disclaimer
Although I can't quote an official response (and I can't guarantee how long these findings will remain true), I just spent some time reverse engineering the logic and it seems to be pretty simple.
Requesting a Review:
When you request a review, StoreKit sends a message to com.apple.itunesstored.xpc, which is responsible for enforcing and tracking limits. If request limits haven't been reached, the XPC process tracks the request and responds with an app review token. Otherwise, it responds with nil.
After the XPC response has been received, StoreKit checks to see whether the token was nil. If it is non-nil, an SKStoreReviewViewController is instantiated and presented in an internal UIWindow. Otherwise, the request is silently ignored. There is no callback or notification you can listen for, and while there is some code in the XPC handler for logging errors, I didn't see any sources of errors in the XPC process.
Validating Limits
As far as the logic behind the limits, it's quite simple. There are two conditions that must be met:
The user must not be prompted more than three times in the past 365 days, regardless of app version.
The user must not be prompted if they rated the app in a prior request, unless:
Their last rating was more than 365 days ago
AND The application version has changed
Although Apple recommends waiting for further engagement over a few weeks before requesting another prompt, at the moment, there is no logic that prevents you from prompting the user three times within three minutes. Those prompts will count for all three of your prompts for the next 365 days though.
tl;dr
StoreKit will silently ignore any excess requests and you can't determine when that happens.
Although you could track your requests yourself to know when you need to redirect to the App Store vs request a review, Apple may change the logic at any point in time. There is no way to programmatically query your limits.
Three prompts per year means three prompts within the past 365 days, regardless of app version. (Updating the app clears the "never prompted again" requirement though.)
There is no limitation of interval between two request review calls.
For your situation, I'd recommend using the new App Store URL that brings users directly to a review composition screen. This will work more consistently while still following the HIG guidelines (since it's in response to a button press).
To automatically open a page on which users can write a review in the App Store, append the query parameter action=write-review to your product URL.
Related
I have implimented SKStoreReviewController in My app. I just want to know how the functionality works. I need to satisfy below requirements.
I need to disply popup in all the 3 cases
For first 10 successful logins
After every 90 days
I don't want to disply rating popup never if he provide the rating.
How do I know if a user gave the rating and also I need to send
response to server if user gave the rating.
SKStoreReviewController submit button is active after your app is live in appStore. The submit button is automatically disable when you're running in debug mode. It's only active when you're launching your app in appStore. That is not mistake from apple or Xcode.
Thank you.
Apple provides some suggested best practices and sample code for requesting reviews.
In answer to your requirements:
This is definitely not best practice; after 10 successful logins might be a reasonable time to ask for a review, but asking each time the user logs in will probably just be annoying.
Again, asking after 90 days is probably a reasonable interval.
By design there is no indication to your app as to whether the review request was shown, nor whether a review was left.
You can link directly to the App Store page where the user can provide a review, however you still have no indication of whether the user actually left a review or simply cancelled out of the web page.
The sample code I linked to shows how to track whether you have requested a review for the current version of your app. You cannot know whether the user has actually reviewed the current version.
I have an application with banking domain (UPI) the very first step or screen the user is presented with a button titled "SEND SMS" to login/register when user clicks on it, a SMS is send from the device using the MFMessageComposeViewController, and based on the mobile number the server respond with weather the user already exists or its a new registration.
Since this is obvious that a valid phone number is required to send SMS or use the application, I am unable to provide a demo account to them.
This is second release of the version, for the first release we have submitted the video of production application and it was live on Appstore, not only this app but I have submitted few other without a demo account but using a video, this time too I have submitted the video, still they ask for the demo account, I have tried to explain them whole process using telephone conversation but no luck. Also did asked them to use there own mobile number on their testing device but they refused to do so.
How can I move forward with this release?
I went through some similar question but didn't find any help.
Apple rejects app because test account not given (as App login via OTP only)
Is demo account mandatory for apple submission?
App meta data rejected , requires demo account.
Note: I don't have OTP functionality in my application, the only way to register is by sending the SMS.
In this annoying situation.
The fact is, generally you have to:
change your app, so that it does have a demo mode, which Apple can use.
It's a total pain in the ass but that's how it is.
Some points,
For example, you could have a "special" number (666-777-8888) which is entered. When that one is entered, the app unlocks and you can see how it works.
It is really bad luck when this happens. It's just one of the reviewers being an idiot. Sometimes if you just submit again it will sail through.
Note that you CAN IN FACT email them and explain the situation, they will give you special handling and they will "actually test it" with a phone number. However, of course this can take time, it takes a long time to get special handling. (Unless your app is already popular / well-known, then they will help you instantly. It's not fair but that's life.)
An important point is this: for the demo mode, note that you do not have to go overboard showing every feature. Apple's review process is a joke anyway. In 99.9% of cases they just glance at your app. If you do have to make an 'Apple demo mode', it's normal that the demo mode only has a few of your features. They are really just checking that it does not crash-upon-launch and that it generally works ok.
{Regarding the last point - indeed they only carefully review your app for policy problems etc once it is popular. This leads to the infuriating situation where controversial apps are approved at first, but then once they "actually look at it" they say you're not allowed to collect donations or use that payment model or whatever the case may be.}
Regarding having a "special demo" mode. It's a nuisance but sometimes you have to do this:
Have a URL like "yourCompany.com/DemoCheck.txt".
When the app launches, see if that exists.
If it does, allow "pain in the ass Apple demo mode"
Now, after apple approves it, in fact remove the URL from your web server, so your app now knows to run in normal consumer mode.
(Note that if you are using any sort of backend, which you probably are, you can do the same thing just using your back end. So just have a value in Firebase or whatever that indicates "Apple demo mode". Once the app goes to production, turn it off.)
Once again, if you're truly doing something important like "a banking app" you, obviously can't have a security hole like an idiotic "apple test version". In that case you can actually contact them and carefully explain the situation and they will, in fact, test it "properly" using a phone etc. But that takes a really long time and is just not practical - consider, you'd have to do that every single time. In practice you need a "apple demo mode".
In an IOS app, I normally validate that purchases have succeeded and been processed by my application by comparing Apple's list of receipts with one that I add to locally when I've processed the purchase myself. This safeguards against things like app crashes during purchase, bugs, etc that can make things get out of sync. I'm trying to do something similar with Amazon.
I have come across statements like this repeatedly in Amazon docs about purchase validation/restoration:
It is possible for a purchase transaction to have more than one Purchase Token representation, so they should not be used as transaction IDs.
This was a huge help as I thought the exact opposite. Unfortunately, I haven't found the rest of the thought: "The transaction ID can be found here:...". I'm starting to think that their transactions don't offer a stable ID...! Please tell me what I'm missing or, if it really doesn't exist, how I can safeguard against the problems I mentioned above?
The initiatePurchaseUpdatesRequest call under Amazon IAP takes an offset parameter which is a permanent identifier for a restore point. Each time you start up you issue an initiatePurchaseUpdatesRequest starting from the last offset you saw (or Offset.BEGINNING the first time). When the response comes in, you save off the offset from the response for the next startup. In this way, any new but unrecorded sales (due to bugs or multiple device issues) will get caught on the next startup. One, minor, impact of this is that you can actually get notified of a purchase twice - once when it occurs and once on the next onPurchaseUpdatesResponse.
As usual you also have the ability for a user to manually request a "restore purchases" that issues the initiatePurchaseUpdatesRequest with the Offset.BEGINNING parameter in case all else fails.
Ps. The actual receipt validation should be performed by calling an Amazon web service from your own server using the receipt values from either the restore or the purchase responses.
With the current Amazon IAP api, keep track of whether you've fulfilled the IAP item by the "requestId" in the PurchaseResponse object. This "requestId" can be used as a sort of pseudo transaction id. You should save this requestId to a server or to the device's local storage.
See the quick start link below for more details:
https://developer.amazon.com/appsandservices/apis/earn/in-app-purchasing/docs/quick-start#7
I'm implementing a trial then subscribe model into my app which allows the user to use the app for free for 14 days, then at the end of the trial it'll alert them that the trial ended and they need to subscribe to continue use.
I'm doing this settings an NSDate object in standardDefaults the first time the app is opened. Then it compares the current date with the stored date, and compares the returned time interval to the number of seconds in 14 days.
My question is this: Do standardDefaults stay in memory if the user deletes the app? If not, how can I prevent a user from deleting then redownloading the app to restart the trial period?
Apple is quite proud about their sandboxing concept and the fact, that if a app is deleted, all the data will be deleted.
The only way of ensuring this information won't be lost will be to save it to a Database on a server and periodical check from your app.
This as technical solution. But make sure, if Apple will allow this in there AppStore if you plan to release it there.
Apple forbids trial versions, though I am not sure, if you could deliver in-app purchased content free for a while and later start billing.
But the main rule is: what ever was given to the user for free must stay free.
There are some apps that have trial periods for certain features. Look at the Puffin Browswer or ChessFree they both offer features that expire. Puffin allows for flash support (actually really cool feature!) and after a few days that feature is removed. Although the rest of the browser is still accessible the main purpose of it is removed.
ChessFree gives you points that you can use for different things, lessons, playing games, taking moves back, etc... I am not sure what happens when you run out of points but it appears that you cannot really do anything anymore.
If I were to implement something like this I would just save a variable in the keychain telling how many days they have left or the date they installed it (as a string). That way it will not be deleted if the app is uninstalled (keychain items stay stored even if the app is removed, so just always check/decrement/increment that as you wish). I would probably keep some features available to users that reach the expired time limit (like Puffin) but I honestly believe that is up to you.
I'm building an iOS app, which provides a service which our website already provides. It's a subscription based service, where all features are enabled when you're subscribed. To get people to sign up for regular payments on the app, it seems like I'll have to go through Apple's in app purchasing API, with auto-renewing subscriptions. That's fine, but the problem is the service users will purchase through the app must also be available on the site. But reading through walkthroughs and the developer guide, it looks like the only way to process transactions is through the app itself, which then can be set up to pass the info to the server. But then I'm imagining this scenario:
User purchases a subscription on the iOS app, goes back and forth between using the site and the iOS app. On the day the user is to be charged, and the days after, they're using just the website, for whatever reason. The server doesn't know they've been billed though, and so features are disabled. In order for the server to find out the user has been billed by Apple, the user has to open the app on their iphone or ipad and sync it with both Apple and my server.
Is there any way for my server to ping Apple directly and get information about the purchases made for my app for a given user? I haven't been able to find anything; the two suggested layouts, with or without server, both use the iOS app as the sole communicator with Apple, aside from having the server verify that information is valid. If it's not possible for the server to get this information first hand, what other possible solution could there be?
Try to not use Apple's built in payment system, and risk getting rejected (with the app duplicating a service that's been available for years online, do we no longer have to use their in app purchasing system anyway?)
If a user is paying through Apple, have the server give them a generous buffer between expected payment dates and when features are disabled (makes the problem happen less frequently but doesn't solve it)
When their account seems expired to the server but it doesn't expect that, email the user a message saying they have to open the app or else their account will not be credited for time purchased (seems like a strange and not really great thing to have to ask a user to do in order to use the service)
This is about all I've been able to think up so far. Anyone have any advice on these solutions, or know of others, or know who I could talk to to try and figure this out?
Yes, you can check on the status of a user's account from your server. There are a few caveats:
First and foremost, Auto-Renewing Subscriptions are reserved for periodicals such as magazines and newspapers. If your app doesn't resemble those, Apple may reject it (as they did mine) and request that you use Non-Renewing Subscriptions (read: Manually-Renewing Subscriptions).
Second: This scenario would require you to store all receipts that you receive on the app, on your server.
Finally: I don't know how your username/password system works, but the user would have to login with the same credentials on your app as they do on your website.
Here's how you check the status of a user's account: Store at least one receipt per user on your server. When you want to check the status, follow Apple's procedure for Verifying App Store Receipts. Send them that one receipt and they'll respond with the latest receipt and the expiration date. Now you'll know, at any given moment, if a person's account is current or not.