24

I'd like to be able to determine which store the user connects to from inside my app, so that I can direct them to some appropriate content for their device AND store. Does anyone know how to get this information?

Basically, if the user is in the UK, and connects to the UK store, I want my function/method to return GB, if in Korea, I want KR, Australia = AU etc. Any help would be appreciated.

pms1969
  • 3,354
  • 1
  • 25
  • 34

7 Answers7

34

The approach of getting the country code of the user's locale will work ... but only if the user's iTunes store is the same as their locale. This won't always be the case.

If you create an in-app purchase item, you can use Apple's StoreKit APIs to find out the user's actual iTunes country even if it's different from their device locale. Here's some code that worked for me:

- (void) requestProductData
{
    SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers:
                                 [NSSet setWithObject: PRODUCT_ID]];
    request.delegate = self;
    [request start];
}

- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    NSArray *myProducts = response.products;
    for (SKProduct* product in myProducts) {
        NSLocale* storeLocale = product.priceLocale;
        storeCountry = (NSString*)CFLocaleGetValue((CFLocaleRef)storeLocale, kCFLocaleCountryCode);
        NSLog(@"Store Country = %@", storeCountry);
    }

    [request release];

    // If product request didn't work, fallback to user's device locale
    if (storeCountry == nil) {
        CFLocaleRef userLocaleRef = CFLocaleCopyCurrent();
        storeCountry = (NSString*)CFLocaleGetValue(userLocaleRef, kCFLocaleCountryCode);
    }

    // Now we're ready to start creating URLs for the itunes store
    [super start];
}
arteku
  • 406
  • 4
  • 7
  • 1
    A bit late to the party for me, and I won't have any chance to use this now myself. If someone else verifies that this does indeed work, and you can get some up-votes, I'll re-mark this as the answer. It's a long time ago now, but I'm pretty sure the StoreKit API wasn't around back then. – pms1969 Apr 04 '12 at 07:14
  • This works. I don't use the same code, but the idea of reading the iTunes Store currency code from `product.priceLocale` definitely works. – Jonas Sourlier Jan 31 '13 at 07:12
  • 1
    hold up.. this only works i you actually _do_ have in-app purchases right? what if you don't? is there another way? – abbood Jun 10 '15 at 10:59
  • 1
    @abbood Can't you create an IAP and use it for this purpose only and never show it to the user? – Claes Oct 29 '15 at 22:55
  • 3
    Our experience is that Apple will not approve an app that uses this technique to detect the territory/region but does not show an in-app purchase to the user. If you show in-app purchases to the user and **also** want to detect the territory/region then this is a valid technique. The Apple reviewers suggested that an alternative if you are trying to restrict some aspect of your app based on region is to use geolocation instead. But, you will need to get Apple's approval to use that since it also violates a review guideline on the use of location data. – Bennett Smith Dec 15 '15 at 19:43
  • Saved my buttocks. Thanks. – jestro Jul 06 '16 at 02:27
3

Since iOS 13.0, Apple introduced the SKStorefront API.

It allows you to check the current AppStore country the user is connected to.

SKStorefront: An object containing the location and unique identifier of an Apple App Store storefront.

Overview

In-app products you create through App Store Connect are available for sale in every region with an App Store. You can use the storefront information to determine the customer's region, and offer in-app products suitable for that region. You must maintain your own list of product identifiers and the storefronts in which you want to make them available.

Topics

  • countryCode: The three-letter code representing the country associated with the App Store storefront.
  • identifier: A value defined by Apple that uniquely identifies an App Store storefront.

https://developer.apple.com/documentation/storekit/skstorefront

jeko
  • 307
  • 2
  • 8
  • 1
    Be careful, because they also say, "Storefront information **may not be used** to develop or enhance a user profile, or track customers for advertising or marketing purposes." – Andrew Kirna Dec 03 '19 at 20:47
  • how can you retrieve it? – Reimond Hill Jun 08 '20 at 14:43
  • 1
    always return the USA for me, even from a UK based device configured with local apple id, going by the above I end up requesting the US products and that always fails as the actual store is GB, maybe its a sandbox thing has anyone used this in production? – Umar Cheema Nov 23 '21 at 19:15
  • 1
    I have the same issue. It returns USA no matter what. – Robert Gummesson Mar 02 '22 at 12:37
2

So far you can use 2 methods with their pros and cons:

StoreFront

->SDK >= 13

->The three-letter code representing the country associated with the App Store storefront

if let storeFront = SKPaymentQueue.default().storefront{
    print("StoreFront CountryCode = ", storeFront.countryCode)
}
else {
    print("StoreFront NOT Available")
}

OR

SKCloudServiceController

-> Available from iOS 9.3.

-> Requires permission. On tvOS it can become messy as I can't find a way to change the permissions in settings...

-> Permission text quite confusing.

let skCloudServiceController = SKCloudServiceController()
SKCloudServiceController.requestAuthorization { (status) in
    guard status == .authorized else {
        return
    }

    skCloudServiceController.requestStorefrontCountryCode(completionHandler: { (countryCode, error)  in
        if let error = error {
            print("Failure: ", error)
        }
            else if let countryCode = countryCode {
            print("Country code: ", countryCode)
        }
    })
}

Don't forget to include that in your .plist file:

<key>NSAppleMusicUsageDescription</key>
<string>Store information</string>
Reimond Hill
  • 4,278
  • 40
  • 52
0

A hard way to get this function is to set up up a single app for every app store country. Each app holds it's own country store information. This assumes, that a user sticks to one store, which should be true for most people.

alex
  • 2,464
  • 23
  • 32
  • Not really the type of solution I'm looking for, although, in a bind, I'll do that. I'm sure there's an easier way, I just don't know what it is. – pms1969 Mar 30 '10 at 09:02
0

I suggest you try iTunes deep links. For example, http://itunes.com/apps/appname should take the user to the local App Store where she spends money.

Costique
  • 23,712
  • 4
  • 76
  • 79
0

I need the same functionality. At the moment I'm considering reading using data from NSLocale as default, but adding a setting in settings.app for user to customise this if it does not match.

This function is taken from an answer to another question of mine.

- (NSString *)getUserCountry
{
    NSLocale *locale = [NSLocale currentLocale];
    return [locale objectForKey: NSLocaleCountryCode];
}
Community
  • 1
  • 1
prendio2
  • 1,885
  • 17
  • 25
  • 3
    Thought of the setting too. But I don't particularly like that as an idea, as for instance, you have a lot of naturally spanish speaking people in the states, who's locale may be completely different from the store they use. I think I'm close to an answer of myself, and I'll post if it works out. – pms1969 Apr 15 '10 at 06:47
  • 1
    I thought this answer to one of my questions might be of interest: http://stackoverflow.com/questions/2639684/itunes-music-store-link-maker-how-to-search-from-within-my-app/2668190#2668190 wouldn't ThierryB's `getUserCountry` method return US for users in US regardless of what their language was set to? – prendio2 Apr 20 '10 at 16:09
  • Thanks, I tried that early on, but it didn't work the way I expected, or returned an incorrect result. Having said that, I can't actually remember having done it on the phone (had done in simulator), so I'll have a play when I sort out my damn provisioning profile and can debug on the phone again. – pms1969 Apr 21 '10 at 04:15
  • OK, seems to have worked (getUserCountry), so giving this the thumbs up. The problem with it of course is if someone (say a Brit) lives the expat life in somewhere like Australia, and has the country code set to GB even tho their store is AU. But unless I can come up with a better method, this will have to do, coupled with an option to change the store. – pms1969 Apr 21 '10 at 07:01
  • 1
    Sorry to have down voted this answer, but this is not correct. The `[NSLocale currentLocale]` does _not_ give you the iTunes Store locale, it gives you the device locale, and that is not the same thing. In fact, I used `[NSLocale currentLocale]` and ran into bugs because of it, until I fixed it by reading the correct store locale from SKProduct's `priceLocale` property. I am living in Australia, but am still using my US iTunes account, so for me these two locales are different as well. – Erik van der Neut Jun 04 '15 at 08:56
-4

You should probably use

[[userDefaults dictionaryRepresentation] objectForKey:@"NSLocaleCode"];

This will return a language code like en_US or en_UK or en_AU or even zh_CN, zh_MY, jp_JP and so on.

Parse the correct codes which you support and direct them accordingly.

chancyWu
  • 14,073
  • 11
  • 62
  • 81
Mugunth
  • 14,461
  • 15
  • 66
  • 94
  • Thanks Mugunth, but locale and store don't necessarily equate to the same thing. I need an elegant way to figure out the store that the user is directed to. I.E. on what store do they spend their money. Don't suppose there's a userdefaults for NSAppStore? – pms1969 Apr 06 '10 at 11:51
  • Down voted, because this does _not_ give the locale of the user's iTunes Store. – Erik van der Neut Jun 04 '15 at 08:59