Starter Tier: Add plans and Mix tasks (#5392)

* fix sandbox plans v4 to be in sync with prod ones

* sync sandbox plans + unify formatting

* create v5 plans in paddle prod + sandbox + Mix.tasks

* add teams and shared links features

* remove unused line of code

* paddle credentials as module attrs

* remove teams and shared links as growth benefits for time being
This commit is contained in:
RobertJoonas 2025-05-15 11:02:43 +01:00 committed by GitHub
parent b64c3a20ce
commit 18907aef63
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 2615 additions and 904 deletions

View File

@ -0,0 +1,342 @@
defmodule Mix.Tasks.CreatePaddleProdPlans do
@moduledoc """
## Utility for creating Paddle plans for production use.
Takes a single `filename` argument which should be of format
`input_plans_v*.json`. That file should live in the `/priv` directory next
to all other plans and it should contain the necessary information about
the production plans to be created.
In order to create the input file:
* Copy an existing `plans_v*.json` (latest recommended) into the new
`input_plans_v*.json` file.
* For every plan object:
* Adjust the generation, limits, features, etc as desired
* Replace `monthly_product_id` with a `monthly_price` (integer)
* Replace `yearly_product_id` with a `yearly_price` (integer)
After this task is finished successfully, the plans will be created in Paddle
with the prices given in the input file. With the creation, every plan gets an
autoincremented ID in Paddle. We will then fetch those exact plans from Paddle
in an API call and use their monthly and yearly product_id's to write
`plans_v*.json`. It will be written taking the input file as the "template"
and replacing the monthly/yearly prices with monthly/yearly product_id's.
The prices will be written into `/priv/plan_prices.json` (instead of the
prod plans output file). Note that this separation is intentional - we only
store prices locally to not rely on Paddle in the dev environment. Otherwise,
Paddle is considered the "source of truth" of plan prices.
## Usage example:
```
mix create_paddle_prod_plans input_plans_v5.json
```
## Requirement 1: Replace the curl command
Unfortunately, there's no API in Paddle that would allow "bulk creating"
plans - it has to be done through the UI. As a hack though, we can automate
the process by copying the curl request with the help of browser devtools.
Therefore, this Mix.Task **does not work out of the box** and the actual curl
command that it executes must be replaced by the developer. Here's how:
0) Access required to the production Paddle account
1) Navigate to https://vendors.paddle.com/subscriptions/plans. Chrome or
Firefox recommended (need to copy a POST request as cURL in a later step)
2) Click the "+ New Plan" button (top right of the screen) to open the form
3) Open browser devtools, fill in the required fields and submit the form.
No need to worry about the form fields since they're provided in this task
(except `_token`) and they *should work* as long as nothing has changed.
4) Find the POST request from the "Network" tab and copy it as cURL
5) Come back here and paste it into the `create_paddle_plan` function
6) Replace the params within the string with the real params (these should
be available in the function already)
## Requirement 2: Paddle production credentials
You also need to obtain the Paddle credentials from prod environment and
replace them into the module attributes. See `@paddle_vendor_id` and
`@paddle_vendor_auth_code`. Those are needed to fetch the plans via an
actual API call after the plans have been created in Paddle.
"""
use Mix.Task
@requirements ["app.config"]
@paddle_vendor_id "REPLACE ME"
@paddle_vendor_auth_code "REPLACE ME"
def run([filename]) do
{:ok, _} = Application.ensure_all_started(:telemetry)
Finch.start_link(name: MyFinch)
if not Regex.match?(~r/^input_plans_v(\d+)\.json$/, filename) do
raise ArgumentError,
"Invalid filename argument. Note the strict format - e.g.: \"input_plans_v5.json\""
end
input_plans =
Application.app_dir(:plausible, ["priv", filename])
|> File.read!()
|> JSON.decode!()
to_be_created_in_paddle =
input_plans
|> Enum.flat_map(fn plan ->
[
create_paddle_plan_attrs(plan, "monthly"),
create_paddle_plan_attrs(plan, "yearly")
]
end)
user_input =
"""
\n
##########################################################################
# #
# !WARNING! #
# #
# You're about to create production plans in Paddle. Multiple #
# consecutive executions will create the same plans again. #
# Please make sure to not leave duplicates behind! #
# #
##########################################################################
* 'y' - proceed and create all plans
* 't' - test only with two plans
* 'h' - halt
What would you like to do?
"""
|> IO.gets()
|> String.trim()
|> String.upcase()
test_run? =
case user_input do
"Y" ->
IO.puts("Creating all plans...")
false
"T" ->
IO.puts("Creating 2 plans just for testing. Make sure to delete them manually!")
true
_ ->
IO.puts("Halting execution per user request.")
System.halt()
end
{paddle_create_count, create_count} =
if test_run? do
{2, 1}
else
{length(to_be_created_in_paddle), length(input_plans)}
end
to_be_created_in_paddle
|> Enum.take(paddle_create_count)
|> Enum.each(&create_paddle_plan/1)
IO.puts("⏳ waiting 3s before fetching the newly created plans...")
Process.sleep(3000)
IO.puts("Fetching the #{create_count} plans created a moment ago...")
created_paddle_plans =
fetch_all_prod_plans()
|> Enum.sort_by(& &1["id"])
|> Enum.take(-paddle_create_count)
file_path_to_write = Path.join("priv", String.replace(filename, "input_", ""))
prod_plans_with_ids_and_prices =
input_plans
|> Enum.take(create_count)
|> write_prod_plans_json_file(file_path_to_write, created_paddle_plans)
IO.puts("✅ Wrote #{create_count} new plans into #{file_path_to_write}!")
if not test_run? do
write_prices(prod_plans_with_ids_and_prices)
IO.puts("✅ Updated `plan_prices.json`.")
end
IO.puts("✅ All done!")
end
defp create_paddle_plan(%{name: name, price: price, type: type, interval_index: interval_index}) do
your_unique_token = "abc"
# Replace this curl command. You should be able to reuse
# the request body after replacing your unique token.
curl_command = """
... REPLACE ME
--data-raw '_token=#{your_unique_token}&plan-id=&default-curr=USD&tmpicon=false&name=#{name}&checkout_custom_message=&taxable_type=standard&interval=#{interval_index}&period=1&type=#{type}&trial_length=&price_USD=#{price}&active_EUR=on&price_EUR=#{price}&active_GBP=on&price_GBP=#{price}'
"""
case curl_quietly(curl_command) do
:ok ->
IO.puts("✅ Created #{name}")
{:error, reason} ->
IO.puts("❌ Halting. The plan #{name} could not be created. Error: #{reason}")
System.halt(1)
end
end
@paddle_interval_indexes %{"monthly" => 2, "yearly" => 5}
defp create_paddle_plan_attrs(plan_with_price, type) do
%{
name: plan_name(plan_with_price, type),
price: plan_with_price["#{type}_price"],
type: type,
interval_index: @paddle_interval_indexes[type]
}
end
defp fetch_all_prod_plans() do
"https://vendors.paddle.com/api/2.0/subscription/plans"
|> fetch_all_paddle_plans(%{
vendor_id: @paddle_vendor_id,
vendor_auth_code: @paddle_vendor_auth_code
})
end
@paddle_plans_api_pagination_limit 500
def fetch_all_paddle_plans(url, paddle_credentials, page \\ 0, fetched \\ 0) do
body =
paddle_credentials
|> Map.merge(%{
limit: @paddle_plans_api_pagination_limit,
offset: page * @paddle_plans_api_pagination_limit
})
|> JSON.encode!()
headers = [
{"Content-type", "application/json"},
{"Accept", "application/json"}
]
request = Finch.build(:post, url, headers, body)
with {:ok, response} <- Finch.request(request, MyFinch),
{:ok, %{"success" => true, "response" => plans} = body} <- JSON.decode(response.body) do
fetched = body["count"] + fetched
total = body["total"]
IO.puts("✅ Successfully fetched #{fetched}/#{body["total"]} plans")
if fetched == total do
plans
else
plans ++ fetch_all_paddle_plans(url, paddle_credentials, page + 1, fetched)
end
else
error ->
IO.puts("❌ Failed to fetch plans from Paddle - #{inspect(error)}")
System.halt(1)
end
end
defp write_prod_plans_json_file(input_plans, filepath, paddle_plans) do
prod_plans_with_prices =
input_plans
|> Enum.map(fn input_plan ->
monthly_plan_name = plan_name(input_plan, "monthly")
yearly_plan_name = plan_name(input_plan, "yearly")
%{"id" => monthly_product_id} =
Enum.find(paddle_plans, &(&1["name"] == monthly_plan_name))
%{"id" => yearly_product_id} =
Enum.find(paddle_plans, &(&1["name"] == yearly_plan_name))
input_plan
|> Map.merge(%{
"monthly_product_id" => to_string(monthly_product_id),
"yearly_product_id" => to_string(yearly_product_id)
})
end)
content =
prod_plans_with_prices
|> Enum.map(fn plan ->
plan
|> Map.drop(["monthly_price", "yearly_price"])
|> order_keys()
end)
|> Jason.encode!(pretty: true)
File.write!(filepath, content)
prod_plans_with_prices
end
@plan_prices_filepath Application.app_dir(:plausible, ["priv", "plan_prices.json"])
defp write_prices(prod_plans_with_ids_and_prices) do
current_prices = File.read!(@plan_prices_filepath) |> JSON.decode!()
new_prices =
prod_plans_with_ids_and_prices
|> Enum.reduce(current_prices, fn plan, prices ->
prices
|> Map.put_new(plan["monthly_product_id"], plan["monthly_price"])
|> Map.put_new(plan["yearly_product_id"], plan["yearly_price"])
end)
|> Enum.sort()
|> Jason.OrderedObject.new()
|> Jason.encode!(pretty: true)
File.write(@plan_prices_filepath, new_prices)
end
@plan_key_order [
"kind",
"generation",
"monthly_pageview_limit",
"monthly_product_id",
"yearly_product_id",
"site_limit",
"team_member_limit",
"features"
]
def order_keys(plan) do
plan
|> Map.to_list()
|> Enum.sort_by(fn {key, _value} ->
Enum.find_index(@plan_key_order, fn ordered_key -> ordered_key == key end) || 99
end)
|> Jason.OrderedObject.new()
end
defp plan_name(plan, type) do
kind = plan["kind"] |> String.capitalize()
type = type |> String.capitalize()
volume =
plan["monthly_pageview_limit"]
|> PlausibleWeb.StatsView.large_number_format(capitalize_k?: true)
"Plausible #{kind} #{type} Plan (#{volume})"
end
def curl_quietly(cmd) do
cmd = String.replace(cmd, "curl", ~s|curl -s -o /dev/null -w "%{http_code}"|)
case System.cmd("sh", ["-c", cmd], stderr_to_stdout: true) do
{"302", 0} ->
:ok
{http_status, 0} ->
{:error, "unexpected HTTP response status (#{http_status}). Expected 302."}
{_, exit_code} ->
{:error, "curl command exited with exit code #{exit_code}"}
end
end
end

View File

@ -1,31 +1,35 @@
defmodule Mix.Tasks.CreatePaddleSandboxPlans do defmodule Mix.Tasks.CreatePaddleSandboxPlans do
@moduledoc """ @moduledoc """
Utility for creating Sandbox plans that are used on staging. The `filename` Utility for creating Sandbox plans that are used on staging. The product of
argument should be the name of the JSON file containing the production plans. this task is a `sandbox_plans_v*.json` file matching with the production
E.g.: `plans_v4.json`. plans, just with the monthly/yearly product_id's of the sandbox plans.
Unfortunately, there's no API in Paddle that would allow "bulk creating" In principle, this task works like `Mix.Tasks.CreatePaddleProdPlans`, with
plans - it has to be done through the UI. As a hack though, we can automate the following differences:
the process by copying the curl request with the help of browser devtools.
Therefore, this Mix.Task **does not work out of the box** and the actual curl * The `filename` argument should be the name of the JSON file containing the
command that it executes must be replaced by the developer. Here's how: production plans (meaning that those should be created as the first step).
No special "input file" required.
0) Obtain access to the Sandbox Paddle account and log in * To copy the curl command from the browser, you need to add a plan from
1) Navigate to https://sandbox-vendors.paddle.com/subscriptions/plans https://sandbox-vendors.paddle.com/subscriptions/plans. Everything else is
2) Click the "+ New Plan" button to open the form the same - please see `create_paddle_prod_plans.ex` for instructions.
3) Open browser devtools, fill in the required fields and submit the form
4) Find the POST request from the "Network" tab and copy it as cURL
5) Come back here and paste it into the `create_paddle_plan` function
6) Replace the params within the string with the real params (these should
be available in the function already)
Once the plans are created successfully, the task will also fetch the IDs * This task can be executed multiple times in a row - it will not create
(i.e. paddle_plan_id's) and write the `sandbox_plans_v*.json` file (which is duplicates in Sandbox Paddle. On staging we can use a specific plan-naming
basically the same set of production plans but with `monthly_product_id` and structure to determine whether a plan has been created already. On prod we
`yearly_product_id` replaced with the sandbox ones). cannot do that since the plan names need to look nice.
* No need to copy paddle API credentials.
## Usage example:
```
mix create_paddle_sandbox_plans plans_v5.json
```
""" """
alias Mix.Tasks.CreatePaddleProdPlans
use Mix.Task use Mix.Task
@requirements ["app.config"] @requirements ["app.config"]
@ -76,7 +80,7 @@ defmodule Mix.Tasks.CreatePaddleSandboxPlans do
file_path_to_write = Path.join("priv", "sandbox_" <> filename) file_path_to_write = Path.join("priv", "sandbox_" <> filename)
create_local_sandbox_plans_json_file(prod_plans, file_path_to_write, paddle_plans_after) write_sandbox_plans_json_file(prod_plans, file_path_to_write, paddle_plans_after)
IO.puts("✅ All done! Wrote #{length(prod_plans)} new plans into #{file_path_to_write}!") IO.puts("✅ All done! Wrote #{length(prod_plans)} new plans into #{file_path_to_write}!")
end end
@ -91,7 +95,7 @@ defmodule Mix.Tasks.CreatePaddleSandboxPlans do
--data-raw '_token=#{your_unique_token}&plan-id=&default-curr=USD&tmpicon=false&name=#{name}&checkout_custom_message=&taxable_type=standard&interval=#{interval_index}&period=1&type=#{type}&trial_length=&price_USD=#{price}&active_EUR=on&price_EUR=#{price}&active_GBP=on&price_GBP=#{price}' --data-raw '_token=#{your_unique_token}&plan-id=&default-curr=USD&tmpicon=false&name=#{name}&checkout_custom_message=&taxable_type=standard&interval=#{interval_index}&period=1&type=#{type}&trial_length=&price_USD=#{price}&active_EUR=on&price_EUR=#{price}&active_GBP=on&price_GBP=#{price}'
""" """
case curl_quietly(curl_command) do case CreatePaddleProdPlans.curl_quietly(curl_command) do
:ok -> :ok ->
IO.puts("✅ Created #{name}") IO.puts("✅ Created #{name}")
@ -101,6 +105,19 @@ defmodule Mix.Tasks.CreatePaddleSandboxPlans do
end end
end end
defp fetch_all_sandbox_plans() do
url = "https://sandbox-vendors.paddle.com/api/2.0/subscription/plans"
paddle_config = Application.get_env(:plausible, :paddle)
paddle_credentials = %{
vendor_id: paddle_config[:vendor_id],
vendor_auth_code: paddle_config[:vendor_auth_code]
}
CreatePaddleProdPlans.fetch_all_paddle_plans(url, paddle_credentials)
end
@paddle_interval_indexes %{"monthly" => 2, "yearly" => 5} @paddle_interval_indexes %{"monthly" => 2, "yearly" => 5}
defp create_paddle_plan_attrs(plan_with_price, type) do defp create_paddle_plan_attrs(plan_with_price, type) do
@ -112,36 +129,15 @@ defmodule Mix.Tasks.CreatePaddleSandboxPlans do
} }
end end
defp fetch_all_sandbox_plans() do defp plan_name(plan, type) do
paddle_config = Application.get_env(:plausible, :paddle) generation = "v#{plan["generation"]}"
kind = plan["kind"]
volume = plan["monthly_pageview_limit"] |> PlausibleWeb.StatsView.large_number_format()
url = "https://sandbox-vendors.paddle.com/api/2.0/subscription/plans" [generation, type, kind, volume] |> Enum.join("_")
body =
JSON.encode!(%{
vendor_id: paddle_config[:vendor_id],
vendor_auth_code: paddle_config[:vendor_auth_code]
})
headers = [
{"Content-type", "application/json"},
{"Accept", "application/json"}
]
request = Finch.build(:post, url, headers, body)
with {:ok, response} <- Finch.request(request, MyFinch),
{:ok, %{"success" => true, "response" => plans} = body} <- JSON.decode(response.body) do
IO.puts("✅ Successfully fetched #{body["count"]}/#{body["total"]} sandbox plans")
plans
else
error ->
IO.puts("❌ Failed to fetch plans from Paddle - #{inspect(error)}")
System.halt(1)
end
end end
defp create_local_sandbox_plans_json_file(prod_plans, filepath, paddle_plans) do defp write_sandbox_plans_json_file(prod_plans, filepath, paddle_plans) do
sandbox_plans = sandbox_plans =
prod_plans prod_plans
|> Enum.map(fn prod_plan -> |> Enum.map(fn prod_plan ->
@ -158,9 +154,11 @@ defmodule Mix.Tasks.CreatePaddleSandboxPlans do
"monthly_product_id" => to_string(sandbox_monthly_product_id), "monthly_product_id" => to_string(sandbox_monthly_product_id),
"yearly_product_id" => to_string(sandbox_yearly_product_id) "yearly_product_id" => to_string(sandbox_yearly_product_id)
}) })
|> CreatePaddleProdPlans.order_keys()
end) end)
File.write!(filepath, JSON.encode!(sandbox_plans)) content = Jason.encode!(sandbox_plans, pretty: true)
File.write!(filepath, content)
end end
defp put_prices(plans) do defp put_prices(plans) do
@ -177,27 +175,4 @@ defmodule Mix.Tasks.CreatePaddleSandboxPlans do
}) })
end) end)
end end
defp plan_name(plan, type) do
generation = "v#{plan["generation"]}"
kind = plan["kind"]
volume = plan["monthly_pageview_limit"] |> PlausibleWeb.StatsView.large_number_format()
[generation, type, kind, volume] |> Enum.join("_")
end
defp curl_quietly(cmd) do
cmd = String.replace(cmd, "curl", ~s|curl -s -o /dev/null -w "%{http_code}"|)
case System.cmd("sh", ["-c", cmd], stderr_to_stdout: true) do
{"302", 0} ->
:ok
{http_status, 0} ->
{:error, "unexpected HTTP response status (#{http_status}). Expected 302."}
{_, exit_code} ->
{:error, "curl command exited with exit code #{exit_code}"}
end
end
end end

View File

@ -72,6 +72,8 @@ defmodule Plausible.Billing.Feature do
@features [ @features [
Plausible.Billing.Feature.Props, Plausible.Billing.Feature.Props,
Plausible.Billing.Feature.Teams,
Plausible.Billing.Feature.SharedLinks,
Plausible.Billing.Feature.Funnels, Plausible.Billing.Feature.Funnels,
Plausible.Billing.Feature.Goals, Plausible.Billing.Feature.Goals,
Plausible.Billing.Feature.RevenueGoals, Plausible.Billing.Feature.RevenueGoals,
@ -198,6 +200,20 @@ defmodule Plausible.Billing.Feature.Props do
toggle_field: :props_enabled toggle_field: :props_enabled
end end
defmodule Plausible.Billing.Feature.Teams do
@moduledoc false
use Plausible.Billing.Feature,
name: :teams,
display_name: "Team Accounts"
end
defmodule Plausible.Billing.Feature.SharedLinks do
@moduledoc false
use Plausible.Billing.Feature,
name: :shared_links,
display_name: "Shared Links"
end
defmodule Plausible.Billing.Feature.SiteSegments do defmodule Plausible.Billing.Feature.SiteSegments do
@moduledoc false @moduledoc false
use Plausible.Billing.Feature, use Plausible.Billing.Feature,

View File

@ -114,6 +114,8 @@ defmodule PlausibleWeb.Components.Billing.PlanBenefits do
Enum.flat_map(plan.features, fn feature_mod -> Enum.flat_map(plan.features, fn feature_mod ->
case feature_mod.name() do case feature_mod.name() do
:goals -> ["Goals and custom events"] :goals -> ["Goals and custom events"]
:teams -> []
:shared_links -> []
:stats_api -> ["Stats API (600 requests per hour)", "Looker Studio Connector"] :stats_api -> ["Stats API (600 requests per hour)", "Looker Studio Connector"]
:revenue_goals -> ["Ecommerce revenue attribution"] :revenue_goals -> ["Ecommerce revenue attribution"]
_ -> [feature_mod.display_name()] _ -> [feature_mod.display_name()]

View File

@ -34,7 +34,9 @@ defmodule PlausibleWeb.Plugins.API.Schemas.Capabilities do
RevenueGoals: false, RevenueGoals: false,
StatsAPI: false, StatsAPI: false,
SitesAPI: false, SitesAPI: false,
SiteSegments: false SiteSegments: false,
Teams: false,
SharedLinks: false
} }
} }
}) })

View File

@ -6,15 +6,17 @@ defmodule PlausibleWeb.StatsView do
PlausibleWeb.Endpoint.url() PlausibleWeb.Endpoint.url()
end end
def large_number_format(n) do def large_number_format(n, opts \\ []) do
k = if Keyword.get(opts, :capitalize_k?, false), do: "K", else: "k"
cond do cond do
n >= 1_000 && n < 1_000_000 -> n >= 1_000 && n < 1_000_000 ->
thousands = trunc(n / 100) / 10 thousands = trunc(n / 100) / 10
if thousands == trunc(thousands) || n >= 100_000 do if thousands == trunc(thousands) || n >= 100_000 do
"#{trunc(thousands)}k" "#{trunc(thousands)}" <> k
else else
"#{thousands}k" "#{thousands}" <> k
end end
n >= 1_000_000 && n < 1_000_000_000 -> n >= 1_000_000 && n < 1_000_000_000 ->

View File

@ -1,33 +1,31 @@
{ {
"558746": 36,
"590753": 288,
"648089": 4800,
"558018": 6, "558018": 6,
"572810": 48,
"558745": 12, "558745": 12,
"558746": 36,
"572810": 48,
"590752": 96, "590752": 96,
"590753": 288,
"597309": 69,
"597310": 552,
"597311": 99,
"597312": 792,
"597485": 18, "597485": 18,
"597486": 144, "597486": 144,
"597487": 27, "597487": 27,
"597488": 216, "597488": 216,
"597642": 48, "597642": 48,
"597643": 384, "597643": 384,
"597309": 69,
"597310": 552,
"597311": 99,
"597312": 792,
"642352": 150, "642352": 150,
"642354": 1200, "642354": 1200,
"642355": 225, "642355": 225,
"642356": 1800, "642356": 1800,
"648089": 4800,
"650652": 330, "650652": 330,
"650653": 2640, "650653": 2640,
"654177": 6,
"653232": 60, "653232": 60,
"654178": 12,
"653234": 120, "653234": 120,
"653237": 20,
"653236": 200, "653236": 200,
"653237": 20,
"653238": 30, "653238": 30,
"653239": 300, "653239": 300,
"653240": 50, "653240": 50,
@ -36,12 +34,14 @@
"653254": 700, "653254": 700,
"653255": 100, "653255": 100,
"653256": 1000, "653256": 1000,
"654181": 150,
"653257": 1500, "653257": 1500,
"654182": 225,
"653258": 2250, "653258": 2250,
"654183": 330,
"653259": 3300, "653259": 3300,
"654177": 6,
"654178": 12,
"654181": 150,
"654182": 225,
"654183": 330,
"749342": 9, "749342": 9,
"749343": 90, "749343": 90,
"749344": 19, "749344": 19,
@ -58,6 +58,38 @@
"749357": 1290, "749357": 1290,
"749358": 169, "749358": 169,
"749359": 1690, "749359": 1690,
"857079": 90,
"857080": 190,
"857081": 290,
"857082": 490,
"857083": 690,
"857084": 890,
"857085": 1290,
"857086": 1690,
"857087": 190,
"857088": 390,
"857089": 590,
"857090": 990,
"857091": 1390,
"857092": 1790,
"857093": 2590,
"857094": 3390,
"857097": 9,
"857098": 19,
"857099": 29,
"857100": 49,
"857101": 69,
"857102": 89,
"857103": 129,
"857104": 169,
"857105": 19,
"857106": 39,
"857107": 59,
"857108": 99,
"857109": 139,
"857110": 179,
"857111": 259,
"857112": 339,
"857481": 19, "857481": 19,
"857482": 190, "857482": 190,
"857483": 39, "857483": 39,
@ -74,36 +106,52 @@
"857500": 2590, "857500": 2590,
"857501": 339, "857501": 339,
"857502": 3390, "857502": 3390,
"857097": 9, "910413": 9,
"857079": 90, "910414": 90,
"857098": 19, "910415": 19,
"857080": 190, "910416": 190,
"857099": 29, "910417": 29,
"857081": 290, "910418": 290,
"857100": 49, "910419": 49,
"857082": 490, "910420": 490,
"857101": 69, "910421": 69,
"857083": 690, "910422": 690,
"857102": 89, "910423": 89,
"857084": 890, "910424": 890,
"857103": 129, "910425": 129,
"857085": 1290, "910426": 1290,
"857104": 169, "910427": 169,
"857086": 1690, "910428": 1690,
"857105": 19, "910429": 14,
"857087": 190, "910430": 140,
"857106": 39, "910431": 29,
"857088": 390, "910432": 290,
"857107": 59, "910433": 44,
"857089": 590, "910434": 440,
"857108": 99, "910435": 74,
"857090": 990, "910436": 740,
"857109": 139, "910437": 104,
"857091": 1390, "910438": 1040,
"857110": 179, "910439": 134,
"857092": 1790, "910440": 1340,
"857111": 259, "910441": 194,
"857093": 2590, "910442": 1940,
"857112": 339, "910443": 254,
"857094": 3390 "910444": 2540,
"910445": 19,
"910446": 190,
"910447": 39,
"910448": 390,
"910449": 59,
"910450": 590,
"910451": 99,
"910452": 990,
"910453": 139,
"910454": 1390,
"910455": 179,
"910456": 1790,
"910457": 259,
"910458": 2590,
"910459": 339,
"910460": 3390
} }

View File

@ -7,7 +7,13 @@
"yearly_product_id": "572810", "yearly_product_id": "572810",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -17,7 +23,13 @@
"yearly_product_id": "590752", "yearly_product_id": "590752",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -27,7 +39,13 @@
"yearly_product_id": "597486", "yearly_product_id": "597486",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -37,7 +55,13 @@
"yearly_product_id": "597488", "yearly_product_id": "597488",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -47,7 +71,13 @@
"yearly_product_id": "597643", "yearly_product_id": "597643",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -57,7 +87,13 @@
"yearly_product_id": "597310", "yearly_product_id": "597310",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -67,7 +103,13 @@
"yearly_product_id": "597312", "yearly_product_id": "597312",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -77,7 +119,13 @@
"yearly_product_id": "642354", "yearly_product_id": "642354",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -87,7 +135,13 @@
"yearly_product_id": "642356", "yearly_product_id": "642356",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -97,6 +151,12 @@
"yearly_product_id": "650653", "yearly_product_id": "650653",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
} }
] ]

View File

@ -7,7 +7,13 @@
"yearly_product_id": "653232", "yearly_product_id": "653232",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -17,7 +23,13 @@
"yearly_product_id": "653234", "yearly_product_id": "653234",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -27,7 +39,13 @@
"yearly_product_id": "653236", "yearly_product_id": "653236",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -37,7 +55,13 @@
"yearly_product_id": "653239", "yearly_product_id": "653239",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -47,7 +71,13 @@
"yearly_product_id": "653242", "yearly_product_id": "653242",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -57,7 +87,13 @@
"yearly_product_id": "653254", "yearly_product_id": "653254",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -67,7 +103,13 @@
"yearly_product_id": "653256", "yearly_product_id": "653256",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -77,7 +119,13 @@
"yearly_product_id": "653257", "yearly_product_id": "653257",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -87,7 +135,13 @@
"yearly_product_id": "653258", "yearly_product_id": "653258",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -97,6 +151,12 @@
"yearly_product_id": "653259", "yearly_product_id": "653259",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
} }
] ]

View File

@ -7,7 +7,13 @@
"yearly_product_id": "749343", "yearly_product_id": "749343",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -17,7 +23,13 @@
"yearly_product_id": "749345", "yearly_product_id": "749345",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -27,7 +39,13 @@
"yearly_product_id": "749347", "yearly_product_id": "749347",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -37,7 +55,13 @@
"yearly_product_id": "749349", "yearly_product_id": "749349",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -47,7 +71,13 @@
"yearly_product_id": "749352", "yearly_product_id": "749352",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -57,7 +87,13 @@
"yearly_product_id": "749355", "yearly_product_id": "749355",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -67,7 +103,13 @@
"yearly_product_id": "749357", "yearly_product_id": "749357",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "growth", "kind": "growth",
@ -77,7 +119,13 @@
"yearly_product_id": "749359", "yearly_product_id": "749359",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","stats_api"] "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
}, },
{ {
"kind": "business", "kind": "business",
@ -87,7 +135,16 @@
"yearly_product_id": "857482", "yearly_product_id": "857482",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"] "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
]
}, },
{ {
"kind": "business", "kind": "business",
@ -97,7 +154,16 @@
"yearly_product_id": "857484", "yearly_product_id": "857484",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"] "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
]
}, },
{ {
"kind": "business", "kind": "business",
@ -107,7 +173,16 @@
"yearly_product_id": "857487", "yearly_product_id": "857487",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"] "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
]
}, },
{ {
"kind": "business", "kind": "business",
@ -117,7 +192,16 @@
"yearly_product_id": "857491", "yearly_product_id": "857491",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"] "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
]
}, },
{ {
"kind": "business", "kind": "business",
@ -127,7 +211,16 @@
"yearly_product_id": "857494", "yearly_product_id": "857494",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"] "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
]
}, },
{ {
"kind": "business", "kind": "business",
@ -137,7 +230,16 @@
"yearly_product_id": "857496", "yearly_product_id": "857496",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"] "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
]
}, },
{ {
"kind": "business", "kind": "business",
@ -147,7 +249,16 @@
"yearly_product_id": "857500", "yearly_product_id": "857500",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"] "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
]
}, },
{ {
"kind": "business", "kind": "business",
@ -157,6 +268,15 @@
"yearly_product_id": "857502", "yearly_product_id": "857502",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"] "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
]
} }
] ]

View File

@ -7,7 +7,11 @@
"yearly_product_id": "857079", "yearly_product_id": "857079",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -18,7 +22,11 @@
"yearly_product_id": "857080", "yearly_product_id": "857080",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -29,7 +37,11 @@
"yearly_product_id": "857081", "yearly_product_id": "857081",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -40,7 +52,11 @@
"yearly_product_id": "857082", "yearly_product_id": "857082",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -51,7 +67,11 @@
"yearly_product_id": "857083", "yearly_product_id": "857083",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -62,7 +82,11 @@
"yearly_product_id": "857084", "yearly_product_id": "857084",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -73,7 +97,11 @@
"yearly_product_id": "857085", "yearly_product_id": "857085",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -84,7 +112,11 @@
"yearly_product_id": "857086", "yearly_product_id": "857086",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -95,7 +127,16 @@
"yearly_product_id": "857087", "yearly_product_id": "857087",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -106,7 +147,16 @@
"yearly_product_id": "857088", "yearly_product_id": "857088",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -117,7 +167,16 @@
"yearly_product_id": "857089", "yearly_product_id": "857089",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -128,7 +187,16 @@
"yearly_product_id": "857090", "yearly_product_id": "857090",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -139,7 +207,16 @@
"yearly_product_id": "857091", "yearly_product_id": "857091",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -150,7 +227,16 @@
"yearly_product_id": "857092", "yearly_product_id": "857092",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -161,7 +247,16 @@
"yearly_product_id": "857093", "yearly_product_id": "857093",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -172,7 +267,16 @@
"yearly_product_id": "857094", "yearly_product_id": "857094",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
} }
] ]

394
priv/plans_v5.json Normal file
View File

@ -0,0 +1,394 @@
[
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 10000,
"monthly_product_id": "910413",
"yearly_product_id": "910414",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 100000,
"monthly_product_id": "910415",
"yearly_product_id": "910416",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 200000,
"monthly_product_id": "910417",
"yearly_product_id": "910418",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 500000,
"monthly_product_id": "910419",
"yearly_product_id": "910420",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 1000000,
"monthly_product_id": "910421",
"yearly_product_id": "910422",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 2000000,
"monthly_product_id": "910423",
"yearly_product_id": "910424",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 5000000,
"monthly_product_id": "910425",
"yearly_product_id": "910426",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 10000000,
"monthly_product_id": "910427",
"yearly_product_id": "910428",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 10000,
"monthly_product_id": "910429",
"yearly_product_id": "910430",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 100000,
"monthly_product_id": "910431",
"yearly_product_id": "910432",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 200000,
"monthly_product_id": "910433",
"yearly_product_id": "910434",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 500000,
"monthly_product_id": "910435",
"yearly_product_id": "910436",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 1000000,
"monthly_product_id": "910437",
"yearly_product_id": "910438",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 2000000,
"monthly_product_id": "910439",
"yearly_product_id": "910440",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 5000000,
"monthly_product_id": "910441",
"yearly_product_id": "910442",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 10000000,
"monthly_product_id": "910443",
"yearly_product_id": "910444",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 10000,
"monthly_product_id": "910445",
"yearly_product_id": "910446",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 100000,
"monthly_product_id": "910447",
"yearly_product_id": "910448",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 200000,
"monthly_product_id": "910449",
"yearly_product_id": "910450",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 500000,
"monthly_product_id": "910451",
"yearly_product_id": "910452",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 1000000,
"monthly_product_id": "910453",
"yearly_product_id": "910454",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 2000000,
"monthly_product_id": "910455",
"yearly_product_id": "910456",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 5000000,
"monthly_product_id": "910457",
"yearly_product_id": "910458",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 10000000,
"monthly_product_id": "910459",
"yearly_product_id": "910460",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
}
]

View File

@ -1,142 +1,162 @@
[ [
{ {
"features": [
"goals",
"props",
"stats_api"
],
"generation": 1,
"kind": "growth", "kind": "growth",
"generation": 1,
"monthly_pageview_limit": 10000, "monthly_pageview_limit": 10000,
"monthly_product_id": "78008", "monthly_product_id": "78008",
"yearly_product_id": "78009",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78009"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 1, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 1,
"monthly_pageview_limit": 100000, "monthly_pageview_limit": 100000,
"monthly_product_id": "78010", "monthly_product_id": "78010",
"yearly_product_id": "78011",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78011"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 1, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 1,
"monthly_pageview_limit": 200000, "monthly_pageview_limit": 200000,
"monthly_product_id": "78012", "monthly_product_id": "78012",
"yearly_product_id": "78013",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78013"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 1, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 1,
"monthly_pageview_limit": 500000, "monthly_pageview_limit": 500000,
"monthly_product_id": "78014", "monthly_product_id": "78014",
"yearly_product_id": "78015",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78015"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 1, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 1,
"monthly_pageview_limit": 1000000, "monthly_pageview_limit": 1000000,
"monthly_product_id": "78016", "monthly_product_id": "78016",
"yearly_product_id": "78017",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78017"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 1, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 1,
"monthly_pageview_limit": 2000000, "monthly_pageview_limit": 2000000,
"monthly_product_id": "78018", "monthly_product_id": "78018",
"yearly_product_id": "78019",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78019"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 1, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 1,
"monthly_pageview_limit": 5000000, "monthly_pageview_limit": 5000000,
"monthly_product_id": "78020", "monthly_product_id": "78020",
"yearly_product_id": "78021",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78021"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 1, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 1,
"monthly_pageview_limit": 10000000, "monthly_pageview_limit": 10000000,
"monthly_product_id": "78022", "monthly_product_id": "78022",
"yearly_product_id": "78023",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78023"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 1, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 1,
"monthly_pageview_limit": 20000000, "monthly_pageview_limit": 20000000,
"monthly_product_id": "78024", "monthly_product_id": "78024",
"yearly_product_id": "78025",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78025"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 1, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 1,
"monthly_pageview_limit": 50000000, "monthly_pageview_limit": 50000000,
"monthly_product_id": "78026", "monthly_product_id": "78026",
"yearly_product_id": "78027",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78027" "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
} }
] ]

View File

@ -1,142 +1,162 @@
[ [
{ {
"features": [
"goals",
"props",
"stats_api"
],
"generation": 2,
"kind": "growth", "kind": "growth",
"generation": 2,
"monthly_pageview_limit": 10000, "monthly_pageview_limit": 10000,
"monthly_product_id": "78053", "monthly_product_id": "78053",
"yearly_product_id": "78054",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78054"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 2, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 2,
"monthly_pageview_limit": 100000, "monthly_pageview_limit": 100000,
"monthly_product_id": "78055", "monthly_product_id": "78055",
"yearly_product_id": "78056",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78056"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 2, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 2,
"monthly_pageview_limit": 200000, "monthly_pageview_limit": 200000,
"monthly_product_id": "78057", "monthly_product_id": "78057",
"yearly_product_id": "78058",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78058"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 2, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 2,
"monthly_pageview_limit": 500000, "monthly_pageview_limit": 500000,
"monthly_product_id": "78059", "monthly_product_id": "78059",
"yearly_product_id": "78060",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78060"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 2, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 2,
"monthly_pageview_limit": 1000000, "monthly_pageview_limit": 1000000,
"monthly_product_id": "78061", "monthly_product_id": "78061",
"yearly_product_id": "78062",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78062"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 2, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 2,
"monthly_pageview_limit": 2000000, "monthly_pageview_limit": 2000000,
"monthly_product_id": "78063", "monthly_product_id": "78063",
"yearly_product_id": "78064",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78064"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 2, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 2,
"monthly_pageview_limit": 5000000, "monthly_pageview_limit": 5000000,
"monthly_product_id": "78065", "monthly_product_id": "78065",
"yearly_product_id": "78066",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78066"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 2, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 2,
"monthly_pageview_limit": 10000000, "monthly_pageview_limit": 10000000,
"monthly_product_id": "78067", "monthly_product_id": "78067",
"yearly_product_id": "78068",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78068"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 2, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 2,
"monthly_pageview_limit": 20000000, "monthly_pageview_limit": 20000000,
"monthly_product_id": "78069", "monthly_product_id": "78069",
"yearly_product_id": "78070",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78070"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 2, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 2,
"monthly_pageview_limit": 50000000, "monthly_pageview_limit": 50000000,
"monthly_product_id": "78071", "monthly_product_id": "78071",
"yearly_product_id": "78072",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78072" "features": [
"goals",
"props",
"stats_api",
"teams",
"shared_links"
]
} }
] ]

View File

@ -1,250 +1,282 @@
[ [
{ {
"features": [
"goals",
"props",
"stats_api"
],
"generation": 3,
"kind": "growth", "kind": "growth",
"generation": 3,
"monthly_pageview_limit": 10000, "monthly_pageview_limit": 10000,
"monthly_product_id": "78073", "monthly_product_id": "78073",
"yearly_product_id": "78074",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78074"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 3,
"monthly_pageview_limit": 100000, "monthly_pageview_limit": 100000,
"monthly_product_id": "78075", "monthly_product_id": "78075",
"yearly_product_id": "78076",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78076"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 3,
"monthly_pageview_limit": 200000, "monthly_pageview_limit": 200000,
"monthly_product_id": "78077", "monthly_product_id": "78077",
"yearly_product_id": "78078",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78078"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 3,
"monthly_pageview_limit": 500000, "monthly_pageview_limit": 500000,
"monthly_product_id": "78079", "monthly_product_id": "78079",
"yearly_product_id": "78080",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78080"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 3,
"monthly_pageview_limit": 1000000, "monthly_pageview_limit": 1000000,
"monthly_product_id": "78081", "monthly_product_id": "78081",
"yearly_product_id": "78082",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78082"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 3,
"monthly_pageview_limit": 2000000, "monthly_pageview_limit": 2000000,
"monthly_product_id": "78083", "monthly_product_id": "78083",
"yearly_product_id": "78084",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78084"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 3,
"monthly_pageview_limit": 5000000, "monthly_pageview_limit": 5000000,
"monthly_product_id": "78085", "monthly_product_id": "78085",
"yearly_product_id": "78086",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78086"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"stats_api" "stats_api",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "growth", "kind": "growth",
"generation": 3,
"monthly_pageview_limit": 10000000, "monthly_pageview_limit": 10000000,
"monthly_product_id": "78087", "monthly_product_id": "78087",
"yearly_product_id": "78088",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78088"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"revenue_goals",
"funnels",
"stats_api", "stats_api",
"site_segments" "teams",
], "shared_links"
"generation": 3, ]
},
{
"kind": "business", "kind": "business",
"generation": 3,
"monthly_pageview_limit": 10000, "monthly_pageview_limit": 10000,
"monthly_product_id": "78089", "monthly_product_id": "78089",
"yearly_product_id": "78090",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78090"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"revenue_goals", "revenue_goals",
"funnels", "funnels",
"stats_api", "stats_api",
"site_segments" "site_segments",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "business", "kind": "business",
"generation": 3,
"monthly_pageview_limit": 100000, "monthly_pageview_limit": 100000,
"monthly_product_id": "78091", "monthly_product_id": "78091",
"yearly_product_id": "78092",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78092"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"revenue_goals", "revenue_goals",
"funnels", "funnels",
"stats_api", "stats_api",
"site_segments" "site_segments",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "business", "kind": "business",
"generation": 3,
"monthly_pageview_limit": 200000, "monthly_pageview_limit": 200000,
"monthly_product_id": "78093", "monthly_product_id": "78093",
"yearly_product_id": "78094",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78094"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"revenue_goals", "revenue_goals",
"funnels", "funnels",
"stats_api", "stats_api",
"site_segments" "site_segments",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "business", "kind": "business",
"generation": 3,
"monthly_pageview_limit": 500000, "monthly_pageview_limit": 500000,
"monthly_product_id": "78095", "monthly_product_id": "78095",
"yearly_product_id": "78096",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78096"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"revenue_goals", "revenue_goals",
"funnels", "funnels",
"stats_api", "stats_api",
"site_segments" "site_segments",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "business", "kind": "business",
"generation": 3,
"monthly_pageview_limit": 1000000, "monthly_pageview_limit": 1000000,
"monthly_product_id": "78097", "monthly_product_id": "78097",
"yearly_product_id": "78098",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78098"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"revenue_goals", "revenue_goals",
"funnels", "funnels",
"stats_api", "stats_api",
"site_segments" "site_segments",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "business", "kind": "business",
"generation": 3,
"monthly_pageview_limit": 2000000, "monthly_pageview_limit": 2000000,
"monthly_product_id": "78099", "monthly_product_id": "78099",
"yearly_product_id": "78100",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78100"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"revenue_goals", "revenue_goals",
"funnels", "funnels",
"stats_api", "stats_api",
"site_segments" "site_segments",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "business", "kind": "business",
"generation": 3,
"monthly_pageview_limit": 5000000, "monthly_pageview_limit": 5000000,
"monthly_product_id": "78101", "monthly_product_id": "78101",
"yearly_product_id": "78102",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78102"
},
{
"features": [ "features": [
"goals", "goals",
"props", "props",
"revenue_goals", "revenue_goals",
"funnels", "funnels",
"stats_api", "stats_api",
"site_segments" "site_segments",
], "teams",
"generation": 3, "shared_links"
]
},
{
"kind": "business", "kind": "business",
"generation": 3,
"monthly_pageview_limit": 10000000, "monthly_pageview_limit": 10000000,
"monthly_product_id": "78107", "monthly_product_id": "78107",
"yearly_product_id": "78109",
"site_limit": 50, "site_limit": 50,
"team_member_limit": "unlimited", "team_member_limit": "unlimited",
"yearly_product_id": "78109" "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
]
} }
] ]

View File

@ -5,9 +5,13 @@
"monthly_pageview_limit": 10000, "monthly_pageview_limit": 10000,
"monthly_product_id": "63842", "monthly_product_id": "63842",
"yearly_product_id": "63859", "yearly_product_id": "63859",
"site_limit":50, "site_limit": 10,
"team_member_limit":"unlimited", "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -16,9 +20,13 @@
"monthly_pageview_limit": 100000, "monthly_pageview_limit": 100000,
"monthly_product_id": "63843", "monthly_product_id": "63843",
"yearly_product_id": "63860", "yearly_product_id": "63860",
"site_limit":50, "site_limit": 10,
"team_member_limit":"unlimited", "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -27,9 +35,13 @@
"monthly_pageview_limit": 200000, "monthly_pageview_limit": 200000,
"monthly_product_id": "63844", "monthly_product_id": "63844",
"yearly_product_id": "63861", "yearly_product_id": "63861",
"site_limit":50, "site_limit": 10,
"team_member_limit":"unlimited", "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -40,7 +52,11 @@
"yearly_product_id": "63862", "yearly_product_id": "63862",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -51,7 +67,11 @@
"yearly_product_id": "63863", "yearly_product_id": "63863",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -62,7 +82,11 @@
"yearly_product_id": "63864", "yearly_product_id": "63864",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -73,7 +97,11 @@
"yearly_product_id": "63865", "yearly_product_id": "63865",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -84,7 +112,11 @@
"yearly_product_id": "63866", "yearly_product_id": "63866",
"site_limit": 10, "site_limit": 10,
"team_member_limit": 3, "team_member_limit": 3,
"features":["goals"], "features": [
"goals",
"teams",
"shared_links"
],
"data_retention_in_years": 3 "data_retention_in_years": 3
}, },
{ {
@ -95,7 +127,16 @@
"yearly_product_id": "63867", "yearly_product_id": "63867",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -106,7 +147,16 @@
"yearly_product_id": "63868", "yearly_product_id": "63868",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -117,7 +167,16 @@
"yearly_product_id": "63869", "yearly_product_id": "63869",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -128,7 +187,16 @@
"yearly_product_id": "63870", "yearly_product_id": "63870",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -139,7 +207,16 @@
"yearly_product_id": "63871", "yearly_product_id": "63871",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -150,7 +227,16 @@
"yearly_product_id": "63872", "yearly_product_id": "63872",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -161,7 +247,16 @@
"yearly_product_id": "63873", "yearly_product_id": "63873",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
}, },
{ {
@ -172,7 +267,16 @@
"yearly_product_id": "63874", "yearly_product_id": "63874",
"site_limit": 50, "site_limit": 50,
"team_member_limit": 10, "team_member_limit": 10,
"features":["goals","props","revenue_goals","funnels","stats_api","site_segments"], "features": [
"goals",
"props",
"revenue_goals",
"funnels",
"stats_api",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5 "data_retention_in_years": 5
} }
] ]

394
priv/sandbox_plans_v5.json Normal file
View File

@ -0,0 +1,394 @@
[
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 10000,
"monthly_product_id": "78943",
"yearly_product_id": "78944",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 100000,
"monthly_product_id": "78945",
"yearly_product_id": "78946",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 200000,
"monthly_product_id": "78947",
"yearly_product_id": "78948",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 500000,
"monthly_product_id": "78949",
"yearly_product_id": "78950",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 1000000,
"monthly_product_id": "78951",
"yearly_product_id": "78952",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 2000000,
"monthly_product_id": "78953",
"yearly_product_id": "78954",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 5000000,
"monthly_product_id": "78955",
"yearly_product_id": "78956",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "starter",
"generation": 5,
"monthly_pageview_limit": 10000000,
"monthly_product_id": "78957",
"yearly_product_id": "78958",
"site_limit": 3,
"team_member_limit": 1,
"features": [
"goals"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 10000,
"monthly_product_id": "78959",
"yearly_product_id": "78960",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 100000,
"monthly_product_id": "78961",
"yearly_product_id": "78962",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 200000,
"monthly_product_id": "78963",
"yearly_product_id": "78964",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 500000,
"monthly_product_id": "78965",
"yearly_product_id": "78966",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 1000000,
"monthly_product_id": "78967",
"yearly_product_id": "78968",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 2000000,
"monthly_product_id": "78969",
"yearly_product_id": "78970",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 5000000,
"monthly_product_id": "78971",
"yearly_product_id": "78972",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "growth",
"generation": 5,
"monthly_pageview_limit": 10000000,
"monthly_product_id": "78973",
"yearly_product_id": "78974",
"site_limit": 10,
"team_member_limit": 3,
"features": [
"goals",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 3
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 10000,
"monthly_product_id": "78975",
"yearly_product_id": "78976",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 100000,
"monthly_product_id": "78977",
"yearly_product_id": "78978",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 200000,
"monthly_product_id": "78979",
"yearly_product_id": "78980",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 500000,
"monthly_product_id": "78981",
"yearly_product_id": "78982",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 1000000,
"monthly_product_id": "78983",
"yearly_product_id": "78984",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 2000000,
"monthly_product_id": "78985",
"yearly_product_id": "78986",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 5000000,
"monthly_product_id": "78987",
"yearly_product_id": "78988",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
},
{
"kind": "business",
"generation": 5,
"monthly_pageview_limit": 10000000,
"monthly_product_id": "78989",
"yearly_product_id": "78990",
"site_limit": 50,
"team_member_limit": 10,
"features": [
"goals",
"props",
"stats_api",
"revenue_goals",
"funnels",
"site_segments",
"teams",
"shared_links"
],
"data_retention_in_years": 5
}
]

View File

@ -3,7 +3,7 @@ defmodule Plausible.Billing.QuotaTest do
use Plausible.DataCase, async: true use Plausible.DataCase, async: true
use Plausible use Plausible
alias Plausible.Billing.{Quota, Plans} alias Plausible.Billing.{Quota, Plans}
alias Plausible.Billing.Feature.{Goals, Props, SitesAPI, StatsAPI} alias Plausible.Billing.Feature.{Goals, Props, SitesAPI, StatsAPI, Teams, SharedLinks}
use Plausible.Teams.Test use Plausible.Teams.Test
@ -581,9 +581,14 @@ defmodule Plausible.Billing.QuotaTest do
team_on_v2 = new_user() |> subscribe_to_plan(@v2_plan_id) |> team_of() team_on_v2 = new_user() |> subscribe_to_plan(@v2_plan_id) |> team_of()
team_on_v3 = new_user() |> subscribe_to_plan(@v3_plan_id) |> team_of() team_on_v3 = new_user() |> subscribe_to_plan(@v3_plan_id) |> team_of()
assert [Goals, Props, StatsAPI] == Plausible.Teams.Billing.allowed_features_for(team_on_v1) assert [Goals, Props, StatsAPI, Teams, SharedLinks] ==
assert [Goals, Props, StatsAPI] == Plausible.Teams.Billing.allowed_features_for(team_on_v2) Plausible.Teams.Billing.allowed_features_for(team_on_v1)
assert [Goals, Props, StatsAPI] == Plausible.Teams.Billing.allowed_features_for(team_on_v3)
assert [Goals, Props, StatsAPI, Teams, SharedLinks] ==
Plausible.Teams.Billing.allowed_features_for(team_on_v2)
assert [Goals, Props, StatsAPI, Teams, SharedLinks] ==
Plausible.Teams.Billing.allowed_features_for(team_on_v3)
end end
test "returns [Goals, Props, StatsAPI] when user is on free_10k plan" do test "returns [Goals, Props, StatsAPI] when user is on free_10k plan" do
@ -625,7 +630,8 @@ defmodule Plausible.Billing.QuotaTest do
team = team_of(user) team = team_of(user)
assert [Goals, Props, StatsAPI] == Plausible.Teams.Billing.allowed_features_for(team) assert [Goals, Props, StatsAPI, Teams, SharedLinks] ==
Plausible.Teams.Billing.allowed_features_for(team)
end end
test "returns all features for enterprise users who have not upgraded yet and are on trial" do test "returns all features for enterprise users who have not upgraded yet and are on trial" do

View File

@ -263,7 +263,7 @@ defmodule PlausibleWeb.AdminControllerTest do
conn = get(conn, "/crm/billing/team/#{team.id}/current_plan") conn = get(conn, "/crm/billing/team/#{team.id}/current_plan")
assert json_response(conn, 200) == %{ assert json_response(conn, 200) == %{
"features" => ["goals"], "features" => ["goals", "teams", "shared_links"],
"monthly_pageview_limit" => 10_000_000, "monthly_pageview_limit" => 10_000_000,
"site_limit" => 10, "site_limit" => 10,
"team_member_limit" => 3 "team_member_limit" => 3

View File

@ -31,7 +31,9 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
"RevenueGoals" => false, "RevenueGoals" => false,
"StatsAPI" => false, "StatsAPI" => false,
"SitesAPI" => false, "SitesAPI" => false,
"SiteSegments" => false "SiteSegments" => false,
"Teams" => false,
"SharedLinks" => false
} }
} }
@ -57,7 +59,9 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
"RevenueGoals" => false, "RevenueGoals" => false,
"StatsAPI" => false, "StatsAPI" => false,
"SitesAPI" => false, "SitesAPI" => false,
"SiteSegments" => false "SiteSegments" => false,
"Teams" => false,
"SharedLinks" => false
} }
} }
@ -85,7 +89,9 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
"RevenueGoals" => true, "RevenueGoals" => true,
"StatsAPI" => true, "StatsAPI" => true,
"SitesAPI" => false, "SitesAPI" => false,
"SiteSegments" => true "SiteSegments" => true,
"Teams" => true,
"SharedLinks" => true
} }
} }
@ -115,7 +121,9 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
"RevenueGoals" => false, "RevenueGoals" => false,
"StatsAPI" => false, "StatsAPI" => false,
"SitesAPI" => false, "SitesAPI" => false,
"SiteSegments" => false "SiteSegments" => false,
"Teams" => true,
"SharedLinks" => true
} }
} }
@ -148,7 +156,9 @@ defmodule PlausibleWeb.Plugins.API.Controllers.CapabilitiesTest do
"RevenueGoals" => false, "RevenueGoals" => false,
"StatsAPI" => true, "StatsAPI" => true,
"SitesAPI" => true, "SitesAPI" => true,
"SiteSegments" => false "SiteSegments" => false,
"Teams" => false,
"SharedLinks" => false
} }
} }