diff --git a/lib/plausible/billing/plans.ex b/lib/plausible/billing/plans.ex
index 9ccdd4ee1011e5cb36249fe548767c0a522cbfc8..08eb6299cdf6e42ae04e601e737bfaf44033de23 100644
--- a/lib/plausible/billing/plans.ex
+++ b/lib/plausible/billing/plans.ex
@@ -1,21 +1,16 @@
 defmodule Plausible.Billing.Plans do
-  @plans_v1 File.read!(Application.app_dir(:plausible) <> "/priv/plans_v1.json")
-            |> Jason.decode!(keys: :atoms)
-  @plans_v2 File.read!(Application.app_dir(:plausible) <> "/priv/plans_v2.json")
-            |> Jason.decode!(keys: :atoms)
-
   @unlisted_plans_v1 [
     %{limit: 150_000_000, yearly_product_id: "648089", yearly_cost: "$4800"}
   ]
 
-  @v2_pricing_date ~D[2021-05-11]
+  @v2_pricing_date ~D[2017-05-11]
 
   def plans_for(user) do
     raw_plans =
       if Timex.before?(user.inserted_at, @v2_pricing_date) do
-        @plans_v1
+        plans_v1()
       else
-        @plans_v2
+        plans_v2()
       end
 
     Enum.map(raw_plans, fn plan -> Map.put(plan, :volume, number_format(plan[:limit])) end)
@@ -75,6 +70,16 @@ defmodule Plausible.Billing.Plans do
   end
 
   defp all_plans() do
-    @plans_v1 ++ @unlisted_plans_v1 ++ @plans_v2
+    plans_v1() ++ @unlisted_plans_v1 ++ plans_v2()
+  end
+
+  defp plans_v1() do
+    File.read!(Application.app_dir(:plausible) <> "/priv/plans_v1.json")
+    |> Jason.decode!(keys: :atoms)
+  end
+
+  defp plans_v2() do
+    File.read!(Application.app_dir(:plausible) <> "/priv/plans_v2.json")
+    |> Jason.decode!(keys: :atoms)
   end
 end
diff --git a/lib/plausible_web/controllers/billing_controller.ex b/lib/plausible_web/controllers/billing_controller.ex
index 52660ff2ba5c80772190beb7668e73ad6dbec198..81a4966f19e564eb3e7038e8344d7c44684b83df 100644
--- a/lib/plausible_web/controllers/billing_controller.ex
+++ b/lib/plausible_web/controllers/billing_controller.ex
@@ -81,6 +81,7 @@ defmodule PlausibleWeb.BillingController do
   def upgrade(conn, _params) do
     usage = Plausible.Billing.usage(conn.assigns[:current_user])
     today = Timex.today()
+    IO.inspect(Plausible.Billing.Plans.plans_for(conn.assigns[:current_user]))
 
     render(conn, "upgrade.html",
       usage: usage,
diff --git a/lib/plausible_web/templates/billing/_plan_option.html.eex b/lib/plausible_web/templates/billing/_plan_option.html.eex
index d1db3b7f9df94ed1646241ed9616644cf6556e32..1c7cdf91c68c2c8fa4fdd002d38a6089f661d543 100644
--- a/lib/plausible_web/templates/billing/_plan_option.html.eex
+++ b/lib/plausible_web/templates/billing/_plan_option.html.eex
@@ -1,7 +1,7 @@
-<tr @click="volume = '<%= @volume %>'" :class="{'border-2 border-green-300 bg-opacity-20 bg-green-300': volume === '<%= @volume %>', 'border-b border-gray-200 cursor-pointer': volume !== '<%= @volume %>'}">
-  <td class="px-6 py-4 text-sm leading-5 dark:text-gray-100" :class="{'font-bold': volume === '<%= @volume %>'}"><%= @volume %></td>
-  <td class="px-6 py-4 text-sm leading-5 dark:text-gray-100" :class="{'font-bold': volume === '<%= @volume %>'}">
-    <span x-show="billingCycle === 'monthly'"><%= @monthly_price %> / mo</span>
-    <span x-show="billingCycle === 'yearly'"><%= @yearly_price %> / yr</span>
+<tr @click="volume = '<%= @plan[:volume] %>'" :class="{'border-2 border-green-300 bg-opacity-20 bg-green-300': volume === '<%= @plan[:volume] %>', 'border-b border-gray-200 cursor-pointer': volume !== '<%= @plan[:volume] %>'}">
+  <td class="px-6 py-4 text-sm leading-5 dark:text-gray-100" :class="{'font-bold': volume === '<%= @plan[:volume] %>'}"><%= @plan[:volume] %></td>
+  <td class="px-6 py-4 text-sm leading-5 dark:text-gray-100" :class="{'font-bold': volume === '<%= @plan[:volume] %>'}">
+    <span x-show="billingCycle === 'monthly'"><span x-text="priceFor(<%= @plan[:monthly_product_id] %>)"></span> / mo</span>
+    <span x-cloak x-show="billingCycle === 'yearly'"><span x-text="priceFor(<%= @plan[:yearly_product_id] %>)"></span> / yr</span>
   </td>
 </tr>
diff --git a/lib/plausible_web/templates/billing/upgrade.html.eex b/lib/plausible_web/templates/billing/upgrade.html.eex
index 4c642b4f4ace322c27554302d25929cbe7d60809..4786798827f786d7d51a89125bdd92bdfdf019bd 100644
--- a/lib/plausible_web/templates/billing/upgrade.html.eex
+++ b/lib/plausible_web/templates/billing/upgrade.html.eex
@@ -1,16 +1,13 @@
+<script type="text/javascript"  src="https://cdnjs.cloudflare.com/ajax/libs/fetch-jsonp/1.1.3/fetch-jsonp.min.js"></script>
 <script>
-  window.plans = function() {
+  plans = function() {
     return {
       rawPlans: <%= raw Jason.encode!(Plausible.Billing.Plans.plans_for(@user)) %>,
+      localizedPlans: null,
       volume: '10k',
       billingCycle: 'monthly',
       selectedPlanPrice() {
-        var selectedPlan = this.rawPlans.find((plan) => plan.volume === this.volume)
-        if (this.billingCycle === 'monthly'){
-          return selectedPlan.monthly_cost
-        } else {
-          return selectedPlan.yearly_cost
-        }
+        return this.priceFor(this.selectedPlanProductId())
       },
       selectedPlanProductId() {
         var selectedPlan = this.rawPlans.find((plan) => plan.volume === this.volume)
@@ -19,6 +16,31 @@
         } else {
           return selectedPlan.yearly_product_id
         }
+      },
+      priceFor(productId) {
+        var plan = this.localizedPlans.find(plan => plan.product_id === Number(productId))
+        var currency = {
+          'USD': '$',
+          'EUR': '€',
+          'GBP': '£'
+        }[plan.currency]
+
+        return currency + plan.price.gross
+      },
+      fetchPlans() {
+        var rawPlans = <%= raw Jason.encode!(Plausible.Billing.Plans.plans_for(@user)) %>
+        var productIds = []
+
+        rawPlans.forEach((plan) => {
+          productIds.push(plan.monthly_product_id)
+          productIds.push(plan.yearly_product_id)
+        })
+
+        fetchJsonp('https://checkout.paddle.com/api/2.0/prices?product_ids=' + productIds.join(','))
+          .then((res) => res.json())
+          .then((data) => {
+            this.localizedPlans = data.response.products
+          })
       }
     }
   }
@@ -30,7 +52,7 @@
 
 <div>
   <div class="flex flex-col w-full max-w-4xl px-4 mx-auto mt-4 md:flex-row">
-    <div x-data="window.plans()" class="flex-1 px-8 py-4 mt-8 mb-4 bg-white rounded shadow-md dark:bg-gray-800">
+    <div x-init="fetchPlans()" x-data="window.plans()" class="flex-1 px-8 py-4 mt-8 mb-4 bg-white rounded shadow-md dark:bg-gray-800">
       <div class="w-full py-4 dark:text-gray-100">
         <span>You've used <b><%= PlausibleWeb.AuthView.delimit_integer(@usage) %></b> billable pageviews in the last 30 days</span>
       </div>
@@ -48,7 +70,7 @@
 
       <div class="pt-6"></div>
 
-      <div class="flex flex-col">
+      <template x-if="localizedPlans" class="flex flex-col">
         <div class="py-2 -my-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
           <div class="inline-block min-w-full overflow-hidden align-middle border-b border-gray-200 shadow sm:rounded-lg dark:border-t dark:border-l dark:border-r dark:shadow-none">
             <table class="min-w-full">
@@ -64,16 +86,18 @@
               </thead>
               <tbody class="bg-white dark:bg-gray-800">
                 <%= for plan <- Plausible.Billing.Plans.plans_for(@user) do %>
-                  <%= render("_plan_option.html", volume: PlausibleWeb.StatsView.large_number_format(plan[:limit]), monthly_price: plan[:monthly_cost], yearly_price: plan[:yearly_cost]) %>
+                  <%= render("_plan_option.html", plan: plan) %>
                 <% end %>
               </tbody>
             </table>
           </div>
         </div>
-      </div>
+      </template>
+
+      <div x-show="!localizedPlans" class="mx-auto my-56 loading sm"><div></div></div>
 
       <div class="mt-6 text-right">
-        <div class="text-sm font-medium dark:text-gray-100">Due today: <b x-text="selectedPlanPrice()">$6</b></div>
+        <div class="text-sm font-medium dark:text-gray-100">Due today: <template x-if="localizedPlans"><b x-text="selectedPlanPrice()">$6</b></template></div>
         <div class="mb-4 text-xs font-medium dark:text-gray-100">+ VAT if applicable</div>
         <span class="inline-flex rounded-md shadow-sm">
           <button type="button" data-theme="none" :data-product="selectedPlanProductId()" data-email="<%= @conn.assigns[:current_user].email %>" data-disable-logout="true" data-passthrough="<%= @conn.assigns[:current_user].id %>" data-success="/billing/upgrade-success" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent paddle_button leading-5 rounded-md hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150">
diff --git a/priv/plans_v2.json b/priv/plans_v2.json
index 67c2098d1f9584654ab300dc9c07ac7edc8e3a97..434ac751dcb852cf18eab38fff7f23dc5d759369 100644
--- a/priv/plans_v2.json
+++ b/priv/plans_v2.json
@@ -2,14 +2,14 @@
   {
     "limit":10000,
     "monthly_cost":"$6",
-    "monthly_product_id":"558018",
+    "monthly_product_id":"654177",
     "yearly_cost":"$60",
     "yearly_product_id":"653232"
   },
   {
     "limit":100000,
     "monthly_cost":"$12",
-    "monthly_product_id":"558745",
+    "monthly_product_id":"654178",
     "yearly_cost":"$120",
     "yearly_product_id":"653234"
   },
@@ -30,9 +30,9 @@
   {
     "limit":1000000,
     "monthly_cost":"$50",
-    "monthly_product_id":"597642",
+    "monthly_product_id":"653240",
     "yearly_cost":"$500",
-    "yearly_product_id":"597643"
+    "yearly_product_id":"653242"
   },
   {
     "limit":2000000,
@@ -51,21 +51,21 @@
   {
     "limit":10000000,
     "monthly_cost":"$150",
-    "monthly_product_id":"642352",
+    "monthly_product_id":"654181",
     "yearly_cost":"$1500",
     "yearly_product_id":"653257"
   },
   {
     "limit":20000000,
     "monthly_cost":"$225",
-    "monthly_product_id":"642355",
+    "monthly_product_id":"654182",
     "yearly_cost":"$2250",
     "yearly_product_id":"653258"
   },
   {
     "limit":50000000,
     "monthly_cost":"$330",
-    "monthly_product_id":"650652",
+    "monthly_product_id":"654183",
     "yearly_cost":"$3300",
     "yearly_product_id":"653259"
   }