antiwork/gumroad · error · ThirdPartyAnalytic::ThirdPartyAnalyticInvalid
Only one analytics block is allowed per product. Please…
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.
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.
- Memberships should have at least one tier.
- Memberships should only have one Tier version category.
- Sorry, shipping destinations have to be unique.
- The product needs to be shippable to at least one…
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/d3a76e57de86ae86.
Report an issue: GitHub.
Appendix: 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)