How to implement versions by country on Rails web app - ruby-on-rails

I need to create a web app that would be different for each country (and not only different language). Let's say the website lists insurance solutions in the country.
For example, users in France typing example.com would need to be sent to http://france.example.com and American users would go to http://us.example.com
All websites would have the same display/layout but the content in the pages would vary as insurance and companies are not the same in each country.
What I'd like is:
in my backend: Manage multiple "country versions" on which I can work to improve features, layout, etc. in a single time without having to update the code on each version. All country versions would stay in similar stat this way.
in the backend: create a filter that "sends" the insurance item I input in my backoffice into the right country-wesbite.
it means for example that the page describing an insurance ALpha in France would only exist in the france version (http://france.example.com/alpha_insurance_description) and not in other country versions.
What kind of architecture must I implement? Are there Rails gems that answer this kind of problematic? (if not maybe some websites describing how to create this kind of multi-country website)

"multi-tenancy" is what you want. The following two railscasts explains two different approches to achieve the same.
http://railscasts.com/episodes/389-multitenancy-with-postgresql
http://railscasts.com/episodes/388-multitenancy-with-scopes
Also you can use subdomain-fu, for subdomain handling and route validation.

I would just use the geoIP data (or user preferences) to find out which country to show and have the content stored in the DB (e.g. insurance companies) with a country code. Seeing as an insurance company will have an address and postcode anyway, this should be pretty simple. That way, both the content and the site language can be set dynamically.
As for the subdomains, you can CNAME all of them to your main site and use a little piece of Rack middleware (hand rolled) to redirect requests to the right subdomain if necessary. After that, the site ignores the subdomain itself and just server content dynamically. Alternatively, you could have some code in the application config that reads the subdomain from the Rack request, extracts the country code, and sets it as a config variable that you then use to flag what country code to use when showing the dynamica content, setting the language, etc.

Related

One URL which will direct customer to the correct store (based on location and language)

We have a multi-store setup with more than 10 stores (different languages and domains), which share many products between them.
The problem:
If we want to do a product promotion on say - Instagram, and include a product URL in the description, it would only be one store (obviously, its dumb to direct a Spanish customer to a Danish site), so:
How to create a "universal" URL which will automatically redirect the customer to the correct store (based on location and language).
Note: Our sites do have hreflang with alternate hrefs set up.
EDIT
Our store is based on Magento framework. My current idea:
1)Have a URL with a parameter of a product ID.
2)This URL directs to a PHP file in which I receive the parameter, by which I can get the product data, then I can loop through the available alternate hrefs (from database).
3)I get the user locale and language (Im not very sure how to do this).
4)Check if any of the available hreflang matches this user and direct them to it.
As you synthesised in your update:
Have an URL with a product ID parameter
In a PHP file, receive the parameter, and retrieve all available languages from the database for that ID
use the Accept-Language header to see which of the languages is the best fit for the user. Pick English if none match, because default world language, yada yada. Using the PHP HTTP_ACCEPT_LANGUAGE server variable has several implementations of a function that does this.
Serve a page with 302 Found status, and Location header that points to the localised URL. It may be good to also include the body with all the metadata (I'm not expert in SEO, and not 100% sure what Google will or won't look at and/or remember when it encounters a 302).

Locale based information on International site

We're building an education platform. The site it's going to be published in different countries, having each country its own subfolder. For example,
France: http://myedusite.com/fr/
Spain: http://myedusite.com/es/
The site has courses belonging to providers
courses have different themes (Arts, Business, Science) and these themes have sub-themes (I'm planning to use ancestry to have a tree structure model)
Courses
providers can create courses if they have an account. The courses created will be published only in the domain they were created.
As an example, if I'm a course's provider and I create an account in http://myedusite.com/fr/, then the courses I create should only be published in http://myedusite.com/fr/.
For this purpose, I thought of defining a Country model with the field iso_3166. This field would be populated with the country codes defined in ISO 3166.
Then, the courses would have a target_country (class: Country), enabling the possibility of choosing where the course is published (if the course's target_country is France it should only be visible in http://myedusite.com/fr/).
Themes
For themes happens something similar, where for each country where the site exists there can be different themes. When a user arrives to http://myedusite.com/xx/, only themes existing in country "xx" will be shown. That implies that each theme should belong to a country.
On the other hand, each course would have one theme.
For dealing with country related information (for example loading cities for a country) I thought of using the country gem.
From the business perspective, we have chosen a bottom-top approach, meaning that only the necessary things are built now, adding features as it's needed.
I see this as a reasonable strategy to make the site international. What I'm afraid of is of choosing wrong and having trouble on the future as new features arrive. I would like to have as much flexibility as possible.
It's the first time I design an international project. Is the approach I've thought of something usual in this kind of sites? Anything I should pay attention to that I didn't mention?
I use navigator.language to get the locale and redirect from JS to whatever URL I want, or add it as a query string. In your case since you only want the language you should split it first, then redirect. In my case I use the full locale code because en is different from AU, US, CA, GB and so on, you'd probably want to consider doing the same especially if you will be displaying prices, dates and so on.
I think there is a way to get this with Rails too, see the Accept-language, accept charset headers.
Once you pass the language/locale to your controller you can then filter data as required.
This also leaves room for some nice SEO tricks if you set up a custom 404 page, engines will go for this.

How to restrict purchases to ONLY IP addresses in the United States using Ruby/Rails?

I have a client who has a requirement that they can't sell particular products 'outside the United States'.
They'd prefer that users can see the site, but when they try to checkout present a message indicating they are outside the United States.
Their site is built in Rails 2.3.8.
Check out the GeoIP gem (make sure to read the instructions, you need to download the GeoLiteCity or GeoLiteCountry database in order for it to work). It uses MaxMind's GeoIP database and can give you the country (or city, in the case of the city database) of an IP address, with some accuracy. There is a commercial database with better accuracy available, which I would recommend for your use case.
However, be advised that this is by no means a definitive solution. Some customers will be turned away wrongfully, and some will be able to order even though they should not. Things like satellite connections, proxy servers and VPN services make IP location impossible, and no database is 100% complete or correct.
What you're looking for is some kind of rough geolocation. One way to get this is to query a DNS zone designed specifically for this; one such zone is described at http://countries.nerd.dk.
I am from Ukraine. And when a particular US shop doesn't want to sell products overseas it usually specifies in the policy/faq/etc that only US bank issued payment cards are accepted.
That seems for me the best solution to solve: "can't sell particular products 'outside the United States'. "
As there are package/mail/freight forwarding companies which can be used by a potential client of that customer though residing outside US but whom the customer won't have to ship directly. That customer would still benefit from those sales but are freed from dialing with burden associated with overseas shipping.
And when you will solve it with geolocation, that customer would still be able making additional money, when people would still be using the site through different kind of proxies, if that customer will be worth it. :)
You can use their data that you pull into your database to check the user's IP address. http://www.ipligence.com/geolocation/ (you still have to worry about proxying)
I would also check where your shipping it to (checking addresses like suggested above), also check the card address with the card backer like VISA, etc..
And suggested above, your money processing agent shouldn't allow any transactions from outside the U.S. on particular items (if possible)
But I did read your statement SOME products may not be allowed to be sold outside the U.S. So you'll need a way to mark those products in your system and then let the user know they are unable to purchase those items, but continue on with others in the cart.
You could use a Rack Middleware, but it will require that you fork it on Github first.
https://github.com/roja/rack-geo
At the moment this project gives you City and Organisation names based on the IP address of the computer making the request - you need Country Code too.
You could add it to the code relatively easily here: https://github.com/roja/rack-geo/blob/master/lib/rack/geo.rb
You could then set a Rack environment variable to indicate if the request is from the USA, in the call method:
Rack::Request.new(env)["born"] = "...in the USA"
Add it to your config file:
config.middleware.use Rack::Geo
And then in your controller you can test if the request has this environment variable set appropriately and redirect to a 'sorry you must be from the USA' page:
if params['born'] == "...in the USA"
redirect_to "/not_from_round_here"
end
Bear in mind that IP address sniffing is fallible. I often take trains in the UK and end up with Google in German.
A geoip alternative is can be found here: http://humbuckercode.co.uk/licks/gems/geoip/
Uses the maxmind libraries, easy to set up, no schema updates needed, fast

URL for the user profile? to be a subdomain or text after the slash?

I'm creating an online based system that has public user profiles for all users..
I'm wondering how to organize the URLs for these public user profiles? What could be better for the SEO and of course for the user friendliness?
{username}.mysystem.com
or
mysystem.com/{username}
or maybe even
mysystem.com/users/{username}
Thanks in advance!
Definitely not a subdomain for SEO Purposes.
I personally prefer the last option mysystem.com/users/{username} as it gives a level of separation from the rest of the application.
This of course requires that {username} is always unique in the database. If it is not (see StackOverflow and the ability to have whatever username you like even if it's taken), then you need to add a Unique Identifier in the url string as well mysystem.com/users/{userID}/{username}
Lastly, if the site ENTIRELY revolves around the user (IE: a blogsite), then you can remove the users from the url string and just go with {username} again providing "username" is unique mysystem.com/{username}
One consideration for SEO is "do the users benefit financially if their profiles get search traffic?"
If the answer is yes, then users have an incentive to build links to their profiles. You won't have any control over the types of links they create. Consequently algorithmic penalties could be applied to your website because one bad egg is trying to increase search traffic.
If you put their profiles on sub domains, then any negative SEO will only affect the sub domain and not the test of the website.

Detect company names that are visiting my site

I'd like to use visitor IP addresses into a company name. This will be used for displaying something like "Hello visitor from Apple Inc." . Note I am looking for the company name, not the domain name. Extra points for determining the originating country. The app is written in Ruby on Rails, but examples in other languages will do. Thanks!
There are databases for this kind of thing, but they are hardly 100% accurate, so I'd think long and hard before using them to make assumptions regarding content you present to your visitors. If you still want to do it, here are two companies that offer databases that include organization level detail:
http://www.maxmind.com/app/ip-location
http://www.ip2location.com/
Edit to clarify based on additional answers:
The organization level detail in the databases from these vendors is different than ISP information, which is what the others are referring to. The databases from the vendors above are actually assigned organizational information based on research, not reverse lookup on IP ownership.
For starters, know that often it is impossible - e.g. many people's connection will be from Insight, or Comcast, or whatever their ISP is. I'm not sure if your intended feature is all that snazzy if you greet me as being "from" Insight Broadband.
You're very likely to get this more wrong than right, but you can get this from a whois client.
For example, to see owners of US addresses (at least), you can whois from the CLI to play around:
whois -h whois.arin.net 17.18.19.20

Resources