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

  1. Dedupe analytics_params by [location, product] client-side before submitting; keep last-write-wins.
  2. Prevent adding a second block for the same product+location in the settings UI.
  3. Server-side, group params with params.group_by { |a| [a[:location], a[:product]] } and reject/merge duplicates before calling save_third_party_analytics.
  4. 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

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


AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21). Data as JSON: /api/errors/d3a76e57de86ae86. Report an issue: GitHub.