antiwork/gumroad · error · ThirdPartyAnalytic::ThirdPartyAnalyticInvalid
Only one analytics block is allowed per product. Please cons
Error message
Only one analytics block is allowed per product. Please consolidate your tracking segments by pasting them into in a single block.
What it means
Raised as ThirdPartyAnalyticInvalid (app/models/third_party_analytic.rb:19) by ThirdPartyAnalytic.save_third_party_analytics when the submitted params contain two analytics entries with the same :location and the same product — the method tracks (location, product_id) pairs in product_hash and refuses the second. One analytics block per product per location (e.g. one for the product page, one for checkout) is the invariant, since each block is injected as a single segment in the page.
Source
Thrown at app/models/third_party_analytic.rb:34
FOR_ALL_PRODUCTS = "#all_products"
LOCATIONS = ["all", "product", "receipt"]
class ThirdPartyAnalyticInvalid < StandardError
end
def self.save_third_party_analytics(analytics_params, seller)
existing_analytics = seller.third_party_analytics.alive
keep_analytics = []
if analytics_params.empty?
existing_analytics.each(&:mark_deleted)
return []
end
product_hash = Hash.new { |hash, key| hash[key] = {} }
analytics_params.each do |third_party_analytic|
product = product_from_permalink(third_party_analytic[:product])
raise ThirdPartyAnalyticInvalid, "Only one analytics block is allowed per product. Please consolidate your tracking segments by pasting them into in a single block." if product_hash[third_party_analytic[:location]][product.try(:id)]
product_hash[third_party_analytic[:location]][product.try(:id)] = true
end
analytics_params.each do |third_party_analytic|
product = product_from_permalink(third_party_analytic[:product])
if third_party_analytic[:id].present?
analytics = seller.third_party_analytics.alive.find_by_external_id(third_party_analytic[:id])
next if analytics.nil?
analytics.link = product if analytics.link != product
analytics.name = third_party_analytic[:name] if third_party_analytic[:name].present?
analytics.location = third_party_analytic[:location] if third_party_analytic[:location].present?
analytics.analytics_code = third_party_analytic[:code] if analytics.analytics_code != third_party_analytic[:code]
analytics.save!
else
analytics = seller.third_party_analytics.create!(analytics_code: third_party_analytic[:code], name: third_party_analytic[:name], location: third_party_analytic[:location], link: product)View on GitHub (pinned to afeacbd394)
Solutions
- Dedupe analytics_params by [location, product] client-side before submitting; keep last-write-wins.
- Prevent adding a second block for the same product+location in the settings UI.
- Server-side, group params with params.group_by { |a| [a[:location], a[:product]] } and reject/merge duplicates before calling save_third_party_analytics.
- Rescue ThirdPartyAnalyticInvalid and show its message.
Example fix
# before
ThirdPartyAnalytic.save_third_party_analytics(analytics_params, seller) # ThirdPartyAnalyticInvalid
# after: last block per (location, product) wins
normalized = analytics_params.uniq { |a| [a[:location], a[:product]] }
ThirdPartyAnalytic.save_third_party_analytics(normalized, seller) Defensive patterns
Strategy: validation
Validate before calling
keys = analytics_params.map { |a| [a[:location], a[:product]] }
return { error: 'One block per product+location.' } if keys.uniq.size != keys.size Try / catch
begin
ThirdPartyAnalytic.save_third_party_analytics(analytics_params, seller)
rescue ThirdPartyAnalytic::ThirdPartyAnalyticInvalid => e
render json: { message: e.message }, status: :unprocessable_entity
end Prevention
- Dedupe by [location, product] before submit; merge tracking segments into one block.
- Settings UI must replace, not append, a product's block for a given location.
- Remember different permalink strings can resolve (product_from_permalink) to the same product — dedupe on resolved product ids.
When it happens
Trigger: POST analytics settings with analytics_params where two entries share both :location and :product (same permalink resolving to the same link) — e.g. duplicate rows appended by the settings form, or per-product blocks duplicated when a form state is applied twice.
Common situations: Analytics settings UI letting the same product+location row be added twice; integrations syncing tracking blocks that append instead of replace; product_from_permalink resolving two different permalink strings to the same product.
Related errors
- Attach at least one file before completing this commission.
- Sorry, shipping destinations have to be unique.
- The product needs to be shippable to at least one destinatio
- You have to confirm your email address before you can do tha
- Memberships should only have one Tier version category.
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/d3a76e57de86ae86.
Report an issue: GitHub.