From ddc882faac29f5c90ba49181c0a2dd682c6cd8e1 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Thu, 31 Aug 2023 20:38:06 +0300 Subject: [PATCH] docs: added multi-region recipe (#4926) * docs: added a multi-region recipe * added other category to plugins list * fix eslint errors * fix broken link * add link * fix sidebar link --- www/docs/content/plugins/other/index.mdx | 5 + www/docs/content/plugins/other/ip-lookup.md | 143 +++++++++ www/docs/content/plugins/overview.mdx | 9 + www/docs/content/recipes/index.mdx | 26 +- www/docs/content/recipes/multi-region.mdx | 309 ++++++++++++++++++++ www/docs/sidebars.js | 29 ++ 6 files changed, 520 insertions(+), 1 deletion(-) create mode 100644 www/docs/content/plugins/other/index.mdx create mode 100644 www/docs/content/plugins/other/ip-lookup.md create mode 100644 www/docs/content/recipes/multi-region.mdx diff --git a/www/docs/content/plugins/other/index.mdx b/www/docs/content/plugins/other/index.mdx new file mode 100644 index 0000000000000..383e19ba2fe24 --- /dev/null +++ b/www/docs/content/plugins/other/index.mdx @@ -0,0 +1,5 @@ +import DocCardList from '@theme/DocCardList'; + +# Other Plugins + + \ No newline at end of file diff --git a/www/docs/content/plugins/other/ip-lookup.md b/www/docs/content/plugins/other/ip-lookup.md new file mode 100644 index 0000000000000..578227a94353c --- /dev/null +++ b/www/docs/content/plugins/other/ip-lookup.md @@ -0,0 +1,143 @@ +--- +addHowToData: true +--- + +# IP Lookup (ipstack) Plugin + +In this document, you’ll learn how to install the IP Lookup plugin on your Medusa backend. + +## Overview + +Location detection in a commerce store is essential for multi-region support. Medusa provides an IP Lookup plugin that integrates the backend with [ipstack](https://ipstack.com/) to allow you to detect a customer’s location and, ultimately, their region. + +This guide explains how you can install and use this plugin. + +--- + +## Prerequisites + +### Medusa Backend + +Before you follow this guide, you must have a Medusa backend installed. If not, you can follow the [quickstart guide](../../create-medusa-app.mdx) to learn how to do it. + +### ipstack Account + +You need an [ipstack account](https://ipstack.com/) before using this plugin. You can create a free account with ipstack on their website. + +--- + +## Install Plugin + +In the root directory of your Medusa backend, run the following command to install the IP Lookup plugin: + +```bash npm2yarn +npm install medusa-plugin-ip-lookup +``` + +Then, add the following environment variable in `.env`: + +```bash +IPSTACK_ACCESS_KEY= +``` + +Where `` is your ipstack account’s access key. It’s available in your ipstack dashboard. + +Finally, add the IP lookup plugin into the plugins array exported as part of the Medusa configuration in `medusa-config.js`: + +```js title=medusa-config.js +const plugins = [ + // other plugins... + { + resolve: `medusa-plugin-ip-lookup`, + options: { + access_token: process.env.IPSTACK_ACCESS_KEY, + }, + }, +] +``` + +--- + +## Test the Plugin + +The plugin provides two resources: the `IpLookupService` and the `preCartCreation` middleware. + +:::note + +Due to how Express resolves the current IP when accessing your website from `localhost`, you won’t be able to test the plugin locally. You can either use tools like ngrok to expose the `9000` port to be accessed publicly, or you have to test it on a deployed backend. + +::: + +### IpLookupService + +The `IpLookupService` can be used in other services, endpoints, or resources to get the user’s location by their IP address. It has only one method `lookupIp` that accepts the IP address as a parameter, sends a request to ipstack’s API, and returns the retrieved result. + +For example, you can use the `IpLookupService` in a custom endpoint and return the user’s region: + +:::tip + +You can learn more about creating an endpoint [here](../../development/endpoints/create.mdx). + +::: + +```ts title=src/api/index.ts +import { Request, Response, Router } from "express" + +export default (rootDirectory: string): Router | Router[] => { + const router = Router() + // ... + router.get( + "/store/customer-region", + async (req: Request, res: Response) => { + const ipLookupService = req.scope.resolve( + "ipLookupService" + ) + const regionService = req.scope.resolve( + "regionService" + ) + + const ip = req.headers["x-forwarded-for"] || + req.socket.remoteAddress + + const { data } = await ipLookupService.lookupIp(ip) + + if (!data.country_code) { + throw new Error ("Couldn't detect country code.") + } + + const region = await regionService + .retrieveByCountryCode(data.country_code) + + res.json({ + region, + }) + } + ) +} +``` + +### preCartCreation + +The `preCartCreation` middleware can be added as a middleware to any route to attach the region ID to that route based on the user’s location. For example, you can use it on the Create Cart endpoint to ensure that the user’s correct region is attached to the cart. + +For example, you can attach it to all `/store` routes to ensure the customer’s region is always detected: + + + +```ts title=src/api/index.ts +import { Router } from "express" + +const { preCartCreation } = require( + "medusa-plugin-ip-lookup/api/medusa-middleware" +).default + +export default ( + rootDirectory: string +): Router | Router[] => { + const router = Router() + // ... + router.use("/store", preCartCreation) + + return router +} +``` diff --git a/www/docs/content/plugins/overview.mdx b/www/docs/content/plugins/overview.mdx index 5e3cf9f4545ea..034020987deda 100644 --- a/www/docs/content/plugins/overview.mdx +++ b/www/docs/content/plugins/overview.mdx @@ -74,6 +74,15 @@ Interested in creating a plugin? Learn more in the [Create Plugin documentation] description: 'Check out official File Service plugins.' } }, + { + type: 'link', + href: '/plugins/other', + label: 'Other Plugins', + customProps: { + icon: Icons['squares-plus-solid'], + description: 'Check out other official plugins.' + } + }, ]} /> diff --git a/www/docs/content/recipes/index.mdx b/www/docs/content/recipes/index.mdx index f48c06538fb99..84a74754f6ff6 100644 --- a/www/docs/content/recipes/index.mdx +++ b/www/docs/content/recipes/index.mdx @@ -72,7 +72,7 @@ Follow this guide if you want to build a B2B/Wholesale store. href: '/recipes/b2b', label: 'Build B2B Store', customProps: { - icon: Icons['credit-card-solid'], + icon: Icons['building-solid'], description: 'Learn how you can build a B2B store in Medusa.' } }} /> @@ -87,6 +87,30 @@ Follow this guide if you want to build a B2B/Wholesale store. --- +## Recipe: Build Multi-Region Store + +Learn how you can build a multi-region store with Medusa. + + + + + +--- + ## Can't find your path? diff --git a/www/docs/content/recipes/multi-region.mdx b/www/docs/content/recipes/multi-region.mdx new file mode 100644 index 0000000000000..3098e4163ed56 --- /dev/null +++ b/www/docs/content/recipes/multi-region.mdx @@ -0,0 +1,309 @@ +--- +addHowToData: true +--- + +import DocCardList from '@theme/DocCardList'; +import Icons from '@theme/Icon'; + +# Multi-Regional Store + +This document guides you through the different features and resources available in Medusa to create a multi-regional store. + +## Overview + +A multi-regional store allows merchants to sell across different countries. This includes supporting each country’s tax rules, currency, available shipping and payment options, and more. + +Medusa provides the necessary features to create a multi-regional store out of the box. This recipe explains how you can benefit from Medusa’s features to create a multi-regional store. + +--- + +## Multi-Region Setup + +With Medusa, you can create an unlimited number of regions in your store. Each region can have its own configurations. These configurations can be managed either through the Medusa admin or the Admin REST APIs. + +### Currency + +Merchants can specify the currency of each region. Multiple regions can have the same currency, but a region can have only one currency. + +This affects what currency are prices shown to the customer in a region. As explained later, this also affects what prices are shown to the customer as well in a region. + +### Tax rates and providers + +Merchants can define for each region a default tax rate and tax rates for specific conditions (for example, for a specific set of products). Each region can also have a different tax provider that calculates the taxes. You can use Medusa’s default tax provider, or create your own tax provider. + +During checkout, the taxes are calculated based on the customer’s region and its taxes configurations and rates. + + + +### Payment and Fulfillment Providers + +Merchants can choose which payment and fulfillment providers are available in which regions. For example, a region may have Stripe enabled as a payment provider, while another may have PayPal enabled instead. + +This affects what payment and shipping methods are shown to the customer during checkout. Customers can only use the methods enabled in their region. + +Medusa provides official plugins for payment and fulfillment providers. You can also create your own providers. + + + +--- + +## Prices Per Region and Currency + +When a merchant sets the price of a product in Medusa, they can specify the price per currency and per region. Merchants can also benefit from this pricing mechanism when adding sales or overriding prices for specific conditions using the [Price Lists feature](../modules/price-lists/overview.mdx). + +Then, customers see the price of a product based on the region they’re in and the region’s currency, and whether any special pricing applies to their case. Medusa has a pricing strategy (which you can override) to show the customer the best price based on their context. + +Using the [tax-inclusive beta feature](../beta.md#tax-inclusive-pricing), merchants can also specify prices that include taxes per currency and region. Medusa then takes care of calculating the tax amount applied to a line item in the cart based on the region’s tax configurations. + + + +--- + +## Product Availability Per Region + +In a multi-regional setup, you may have products that should only be available in certain regions. Using the Sales Channels feature, you can control the availability of products within different channels. + +Sales channels aren’t directly associated with regions by default, but you can create a custom relation between the `SalesChannel` entity and the `Region` entity. Alternatively, you can utilize the `metadata` attribute of each entity, which is an attribute that can be used to add custom data, to set the ID of the associated sales channel or region for each entity. + +Then, when a customer is viewing the products from a region, only the products available in the region’s associated sales channel are retrieved and shown to the customer. + +This also allows you to create or deploy different storefronts for different regions, if necessary. Each storefront only shows the products available in a region and its sales channel. + +It should also be noted that a cart is associated with a region and a sales channel. So, customers can only buy a product if it belongs to the same sales channel as the cart. + + + +--- + +## Multi-Warehouse Support + +Medusa provides Multi-warehouse features that allow you to manage your inventory across different locations. Merchants can then control which location an item in an order is fulfilled from, allowing them to keep a correct inventory count across locations and selling channels. + +In a multi-regional setup, this can allow you to manage your inventory through Medusa across the different regions you serve. Your products’ inventory and availability aren’t bound to a single stock location, and customers are always shown accurate inventory information based on the location associated with their sales channel. + + + +--- + +## Multi-Lingual Setup with Third-Party CMS + +Medusa can be integrated with any third-party services, including Content Management Systems (CMS). With a third-party CMS, you can benefit from rich CMS features, including managing your content in multiple languages. This allows you to cater to customers’ different languages in the regions you serve. + +Medusa provides an official Contentful plugin and a community Strapi plugin. You can also create your own CMS plugin that integrates with your preferred CMS platform to provide multi-lingual features. + + + +--- + +## Automatic Location Detection + +When you sell across regions, it’s important to be able to detect the customer’s region and provide them with the products, prices, and content relevant to them without requiring actions from their side. + +Medusa provides an IP Lookup plugin that allows you to detect a customer’s location and, ultimately, their region using [ipstack](https://ipstack.com/). You can also create a plugin that detects the location through a different logic. + + + +--- + +## Additional Features and Development Resources + +Medusa provides other essential commerce features and development resources to help you build your multi-region store. + + \ No newline at end of file diff --git a/www/docs/sidebars.js b/www/docs/sidebars.js index 755ba5f071359..442cd98bf8a2f 100644 --- a/www/docs/sidebars.js +++ b/www/docs/sidebars.js @@ -62,6 +62,11 @@ module.exports = { id: "recipes/b2b", label: "B2B / Wholesale", }, + { + type: "doc", + id: "recipes/multi-region", + label: "Multi-Region Store", + }, ], }, { @@ -2285,6 +2290,30 @@ module.exports = { }, ], }, + { + type: "category", + label: "Other", + collapsible: false, + link: { + type: "doc", + id: "plugins/other/index", + }, + customProps: { + sidebar_is_group_headline: true, + }, + items: [ + { + type: "doc", + id: "plugins/other/ip-lookup", + label: "IP Lookup", + customProps: { + iconName: "bolt-solid", + description: + "Learn how to integrate ipstack to access the user's region.", + }, + }, + ], + }, ], ], userGuideSidebar: [