package ga

import (
	"net/http"
	"net/url"
)

//WARNING: This file was generated. Do not edit.

//Client Hit Type
type Client struct {
	//Use TLS when Send()ing
	UseTLS                              bool
	HttpClient                          *http.Client
	protocolVersion                     string
	protocolVersionSet                  bool
	trackingID                          string
	anonymizeIP                         bool
	anonymizeIPSet                      bool
	dataSource                          string
	dataSourceSet                       bool
	queueTime                           int64
	queueTimeSet                        bool
	cacheBuster                         string
	cacheBusterSet                      bool
	clientID                            string
	clientIDSet                         bool
	userID                              string
	userIDSet                           bool
	sessionControl                      string
	sessionControlSet                   bool
	iPOverride                          string
	iPOverrideSet                       bool
	userAgentOverride                   string
	userAgentOverrideSet                bool
	geographicalOverride                string
	geographicalOverrideSet             bool
	documentReferrer                    string
	documentReferrerSet                 bool
	campaignName                        string
	campaignNameSet                     bool
	campaignSource                      string
	campaignSourceSet                   bool
	campaignMedium                      string
	campaignMediumSet                   bool
	campaignKeyword                     string
	campaignKeywordSet                  bool
	campaignContent                     string
	campaignContentSet                  bool
	campaignID                          string
	campaignIDSet                       bool
	googleAdWordsID                     string
	googleAdWordsIDSet                  bool
	googleDisplayAdsID                  string
	googleDisplayAdsIDSet               bool
	screenResolution                    string
	screenResolutionSet                 bool
	viewportSize                        string
	viewportSizeSet                     bool
	documentEncoding                    string
	documentEncodingSet                 bool
	screenColors                        string
	screenColorsSet                     bool
	userLanguage                        string
	userLanguageSet                     bool
	javaEnabled                         bool
	javaEnabledSet                      bool
	flashVersion                        string
	flashVersionSet                     bool
	hitType                             string
	nonInteractionHit                   bool
	nonInteractionHitSet                bool
	documentLocationURL                 string
	documentLocationURLSet              bool
	documentHostName                    string
	documentHostNameSet                 bool
	documentPath                        string
	documentPathSet                     bool
	documentTitle                       string
	documentTitleSet                    bool
	screenName                          string
	screenNameSet                       bool
	linkID                              string
	linkIDSet                           bool
	applicationName                     string
	applicationNameSet                  bool
	applicationID                       string
	applicationIDSet                    bool
	applicationVersion                  string
	applicationVersionSet               bool
	applicationInstallerID              string
	applicationInstallerIDSet           bool
	productSKU                          string
	productSKUSet                       bool
	productName                         string
	productNameSet                      bool
	productBrand                        string
	productBrandSet                     bool
	productCategory                     string
	productCategorySet                  bool
	productVariant                      string
	productVariantSet                   bool
	productPrice                        float64
	productPriceSet                     bool
	productQuantity                     int64
	productQuantitySet                  bool
	productCouponCode                   string
	productCouponCodeSet                bool
	productPosition                     int64
	productPositionSet                  bool
	productCustomDimension              string
	productCustomDimensionSet           bool
	productCustomMetric                 int64
	productCustomMetricSet              bool
	productAction                       string
	productActionSet                    bool
	transactionID                       string
	transactionIDSet                    bool
	affiliation                         string
	affiliationSet                      bool
	revenue                             float64
	revenueSet                          bool
	tax                                 float64
	taxSet                              bool
	shipping                            float64
	shippingSet                         bool
	couponCode                          string
	couponCodeSet                       bool
	productActionList                   string
	productActionListSet                bool
	checkoutStep                        int64
	checkoutStepSet                     bool
	checkoutStepOption                  string
	checkoutStepOptionSet               bool
	productImpressionListName           string
	productImpressionListNameSet        bool
	productImpressionSKU                string
	productImpressionSKUSet             bool
	productImpressionName               string
	productImpressionNameSet            bool
	productImpressionBrand              string
	productImpressionBrandSet           bool
	productImpressionCategory           string
	productImpressionCategorySet        bool
	productImpressionVariant            string
	productImpressionVariantSet         bool
	productImpressionPosition           int64
	productImpressionPositionSet        bool
	productImpressionPrice              float64
	productImpressionPriceSet           bool
	productImpressionCustomDimension    string
	productImpressionCustomDimensionSet bool
	productImpressionCustomMetric       int64
	productImpressionCustomMetricSet    bool
	promotionID                         string
	promotionIDSet                      bool
	promotionName                       string
	promotionNameSet                    bool
	promotionCreative                   string
	promotionCreativeSet                bool
	promotionPosition                   string
	promotionPositionSet                bool
	promotionAction                     string
	promotionActionSet                  bool
	customDimension                     string
	customDimensionSet                  bool
	customMetric                        int64
	customMetricSet                     bool
	experimentID                        string
	experimentIDSet                     bool
	experimentVariant                   string
	experimentVariantSet                bool
	dimensionIndex                      string
	dimensionIndexSet                   bool
	listIndex                           string
	listIndexSet                        bool
	metricIndex                         string
	metricIndexSet                      bool
	productIndex                        string
	productIndexSet                     bool
	promoIndex                          string
	promoIndexSet                       bool
}

func (c *Client) setType(h hitType) {
	switch h.(type) {
	case *Event:
		c.hitType = "event"
	case *Exception:
		c.hitType = "exception"
	case *Item:
		c.hitType = "item"
	case *Pageview:
		c.hitType = "pageview"
	case *Screenview:
		c.hitType = "screenview"
	case *Social:
		c.hitType = "social"
	case *Timing:
		c.hitType = "timing"
	case *Transaction:
		c.hitType = "transaction"
	}
}

func (h *Client) addFields(v url.Values) error {
	if h.protocolVersionSet {
		v.Add("v", h.protocolVersion)
	}
	v.Add("tid", h.trackingID)
	if h.anonymizeIPSet {
		v.Add("aip", bool2str(h.anonymizeIP))
	}
	if h.dataSourceSet {
		v.Add("ds", h.dataSource)
	}
	if h.queueTimeSet {
		v.Add("qt", int2str(h.queueTime))
	}
	if h.cacheBusterSet {
		v.Add("z", h.cacheBuster)
	}
	if h.clientIDSet {
		v.Add("cid", h.clientID)
	}
	if h.userIDSet {
		v.Add("uid", h.userID)
	}
	if h.sessionControlSet {
		v.Add("sc", h.sessionControl)
	}
	if h.iPOverrideSet {
		v.Add("uip", h.iPOverride)
	}
	if h.userAgentOverrideSet {
		v.Add("ua", h.userAgentOverride)
	}
	if h.geographicalOverrideSet {
		v.Add("geoid", h.geographicalOverride)
	}
	if h.documentReferrerSet {
		v.Add("dr", h.documentReferrer)
	}
	if h.campaignNameSet {
		v.Add("cn", h.campaignName)
	}
	if h.campaignSourceSet {
		v.Add("cs", h.campaignSource)
	}
	if h.campaignMediumSet {
		v.Add("cm", h.campaignMedium)
	}
	if h.campaignKeywordSet {
		v.Add("ck", h.campaignKeyword)
	}
	if h.campaignContentSet {
		v.Add("cc", h.campaignContent)
	}
	if h.campaignIDSet {
		v.Add("ci", h.campaignID)
	}
	if h.googleAdWordsIDSet {
		v.Add("gclid", h.googleAdWordsID)
	}
	if h.googleDisplayAdsIDSet {
		v.Add("dclid", h.googleDisplayAdsID)
	}
	if h.screenResolutionSet {
		v.Add("sr", h.screenResolution)
	}
	if h.viewportSizeSet {
		v.Add("vp", h.viewportSize)
	}
	if h.documentEncodingSet {
		v.Add("de", h.documentEncoding)
	}
	if h.screenColorsSet {
		v.Add("sd", h.screenColors)
	}
	if h.userLanguageSet {
		v.Add("ul", h.userLanguage)
	}
	if h.javaEnabledSet {
		v.Add("je", bool2str(h.javaEnabled))
	}
	if h.flashVersionSet {
		v.Add("fl", h.flashVersion)
	}
	v.Add("t", h.hitType)
	if h.nonInteractionHitSet {
		v.Add("ni", bool2str(h.nonInteractionHit))
	}
	if h.documentLocationURLSet {
		v.Add("dl", h.documentLocationURL)
	}
	if h.documentHostNameSet {
		v.Add("dh", h.documentHostName)
	}
	if h.documentPathSet {
		v.Add("dp", h.documentPath)
	}
	if h.documentTitleSet {
		v.Add("dt", h.documentTitle)
	}
	if h.screenNameSet {
		v.Add("cd", h.screenName)
	}
	if h.linkIDSet {
		v.Add("linkid", h.linkID)
	}
	if h.applicationNameSet {
		v.Add("an", h.applicationName)
	}
	if h.applicationIDSet {
		v.Add("aid", h.applicationID)
	}
	if h.applicationVersionSet {
		v.Add("av", h.applicationVersion)
	}
	if h.applicationInstallerIDSet {
		v.Add("aiid", h.applicationInstallerID)
	}
	if h.productSKUSet {
		v.Add("pr"+h.productIndex+"id", h.productSKU)
	}
	if h.productNameSet {
		v.Add("pr"+h.productIndex+"nm", h.productName)
	}
	if h.productBrandSet {
		v.Add("pr"+h.productIndex+"br", h.productBrand)
	}
	if h.productCategorySet {
		v.Add("pr"+h.productIndex+"ca", h.productCategory)
	}
	if h.productVariantSet {
		v.Add("pr"+h.productIndex+"va", h.productVariant)
	}
	if h.productPriceSet {
		v.Add("pr"+h.productIndex+"pr", float2str(h.productPrice))
	}
	if h.productQuantitySet {
		v.Add("pr"+h.productIndex+"qt", int2str(h.productQuantity))
	}
	if h.productCouponCodeSet {
		v.Add("pr"+h.productIndex+"cc", h.productCouponCode)
	}
	if h.productPositionSet {
		v.Add("pr"+h.productIndex+"ps", int2str(h.productPosition))
	}
	if h.productCustomDimensionSet {
		v.Add("pr"+h.productIndex+"cd"+h.dimensionIndex+"", h.productCustomDimension)
	}
	if h.productCustomMetricSet {
		v.Add("pr"+h.productIndex+"cm"+h.metricIndex+"", int2str(h.productCustomMetric))
	}
	if h.productActionSet {
		v.Add("pa", h.productAction)
	}
	if h.transactionIDSet {
		v.Add("ti", h.transactionID)
	}
	if h.affiliationSet {
		v.Add("ta", h.affiliation)
	}
	if h.revenueSet {
		v.Add("tr", float2str(h.revenue))
	}
	if h.taxSet {
		v.Add("tt", float2str(h.tax))
	}
	if h.shippingSet {
		v.Add("ts", float2str(h.shipping))
	}
	if h.couponCodeSet {
		v.Add("tcc", h.couponCode)
	}
	if h.productActionListSet {
		v.Add("pal", h.productActionList)
	}
	if h.checkoutStepSet {
		v.Add("cos", int2str(h.checkoutStep))
	}
	if h.checkoutStepOptionSet {
		v.Add("col", h.checkoutStepOption)
	}
	if h.productImpressionListNameSet {
		v.Add("il"+h.listIndex+"nm", h.productImpressionListName)
	}
	if h.productImpressionSKUSet {
		v.Add("il"+h.listIndex+"pi"+h.productIndex+"id", h.productImpressionSKU)
	}
	if h.productImpressionNameSet {
		v.Add("il"+h.listIndex+"pi"+h.productIndex+"nm", h.productImpressionName)
	}
	if h.productImpressionBrandSet {
		v.Add("il"+h.listIndex+"pi"+h.productIndex+"br", h.productImpressionBrand)
	}
	if h.productImpressionCategorySet {
		v.Add("il"+h.listIndex+"pi"+h.productIndex+"ca", h.productImpressionCategory)
	}
	if h.productImpressionVariantSet {
		v.Add("il"+h.listIndex+"pi"+h.productIndex+"va", h.productImpressionVariant)
	}
	if h.productImpressionPositionSet {
		v.Add("il"+h.listIndex+"pi"+h.productIndex+"ps", int2str(h.productImpressionPosition))
	}
	if h.productImpressionPriceSet {
		v.Add("il"+h.listIndex+"pi"+h.productIndex+"pr", float2str(h.productImpressionPrice))
	}
	if h.productImpressionCustomDimensionSet {
		v.Add("il"+h.listIndex+"pi"+h.productIndex+"cd"+h.dimensionIndex+"", h.productImpressionCustomDimension)
	}
	if h.productImpressionCustomMetricSet {
		v.Add("il"+h.listIndex+"pi"+h.productIndex+"cm"+h.metricIndex+"", int2str(h.productImpressionCustomMetric))
	}
	if h.promotionIDSet {
		v.Add("promo"+h.promoIndex+"id", h.promotionID)
	}
	if h.promotionNameSet {
		v.Add("promo"+h.promoIndex+"nm", h.promotionName)
	}
	if h.promotionCreativeSet {
		v.Add("promo"+h.promoIndex+"cr", h.promotionCreative)
	}
	if h.promotionPositionSet {
		v.Add("promo"+h.promoIndex+"ps", h.promotionPosition)
	}
	if h.promotionActionSet {
		v.Add("promoa", h.promotionAction)
	}
	if h.customDimensionSet {
		v.Add("cd"+h.dimensionIndex+"", h.customDimension)
	}
	if h.customMetricSet {
		v.Add("cm"+h.metricIndex+"", int2str(h.customMetric))
	}
	if h.experimentIDSet {
		v.Add("xid", h.experimentID)
	}
	if h.experimentVariantSet {
		v.Add("xvar", h.experimentVariant)
	}
	return nil
}

// The Protocol version. The current value is '1'. This will
// only change when there are changes made that are not backwards
// compatible.
func (h *Client) ProtocolVersion(protocolVersion string) *Client {
	h.protocolVersion = protocolVersion
	h.protocolVersionSet = true
	return h
}

// When present, the IP address of the sender will be anonymized.
// For example, the IP will be anonymized if any of the following
// parameters are present in the payload: &aip=, &aip=0, or
// &aip=1
func (h *Client) AnonymizeIP(anonymizeIP bool) *Client {
	h.anonymizeIP = anonymizeIP
	h.anonymizeIPSet = true
	return h
}

// Indicates the data source of the hit. Hits sent from analytics.js
// will have data source set to 'web'; hits sent from one of
// the mobile SDKs will have data source set to 'app'.
func (h *Client) DataSource(dataSource string) *Client {
	h.dataSource = dataSource
	h.dataSourceSet = true
	return h
}

// Used to collect offline / latent hits. The value represents
// the time delta (in milliseconds) between when the hit being
// reported occurred and the time the hit was sent. The value
// must be greater than or equal to 0. Values greater than
// four hours may lead to hits not being processed.
func (h *Client) QueueTime(queueTime int64) *Client {
	h.queueTime = queueTime
	h.queueTimeSet = true
	return h
}

// Used to send a random number in GET requests to ensure browsers
// and proxies don't cache hits. It should be sent as the final
// parameter of the request since we've seen some 3rd party
// internet filtering software add additional parameters to
// HTTP requests incorrectly. This value is not used in reporting.
func (h *Client) CacheBuster(cacheBuster string) *Client {
	h.cacheBuster = cacheBuster
	h.cacheBusterSet = true
	return h
}

// This anonymously identifies a particular user, device, or
// browser instance. For the web, this is generally stored
// as a first-party cookie with a two-year expiration. For
// mobile apps, this is randomly generated for each particular
// instance of an application install. The value of this field
// should be a random UUID (version 4) as described in http://www.ietf.org/rfc/rfc4122.txt
func (h *Client) ClientID(clientID string) *Client {
	h.clientID = clientID
	h.clientIDSet = true
	return h
}

// This is intended to be a known identifier for a user provided
// by the site owner/tracking library user. It may not itself
// be PII (personally identifiable information). The value
// should never be persisted in GA cookies or other Analytics
// provided storage.
func (h *Client) UserID(userID string) *Client {
	h.userID = userID
	h.userIDSet = true
	return h
}

// Used to control the session duration. A value of 'start'
// forces a new session to start with this hit and 'end' forces
// the current session to end with this hit. All other values
// are ignored.
func (h *Client) SessionControl(sessionControl string) *Client {
	h.sessionControl = sessionControl
	h.sessionControlSet = true
	return h
}

// The IP address of the user. This should be a valid IP address
// in IPv4 or IPv6 format. It will always be anonymized just
// as though &aip (anonymize IP) had been used.
func (h *Client) IPOverride(iPOverride string) *Client {
	h.iPOverride = iPOverride
	h.iPOverrideSet = true
	return h
}

// The User Agent of the browser. Note that Google has libraries
// to identify real user agents. Hand crafting your own agent
// could break at any time.
func (h *Client) UserAgentOverride(userAgentOverride string) *Client {
	h.userAgentOverride = userAgentOverride
	h.userAgentOverrideSet = true
	return h
}

// The geographical location of the user. The geographical
// ID should be a two letter country code or a criteria ID
// representing a city or region (see http://developers.google.com/analytics/devguides/collection/protocol/v1/geoid).
// This parameter takes precedent over any location derived
// from IP address, including the IP Override parameter. An
// invalid code will result in geographical dimensions to be
// set to '(not set)'.
func (h *Client) GeographicalOverride(geographicalOverride string) *Client {
	h.geographicalOverride = geographicalOverride
	h.geographicalOverrideSet = true
	return h
}

// Specifies which referral source brought traffic to a website.
// This value is also used to compute the traffic source. The
// format of this value is a URL.
func (h *Client) DocumentReferrer(documentReferrer string) *Client {
	h.documentReferrer = documentReferrer
	h.documentReferrerSet = true
	return h
}

// Specifies the campaign name.
func (h *Client) CampaignName(campaignName string) *Client {
	h.campaignName = campaignName
	h.campaignNameSet = true
	return h
}

// Specifies the campaign source.
func (h *Client) CampaignSource(campaignSource string) *Client {
	h.campaignSource = campaignSource
	h.campaignSourceSet = true
	return h
}

// Specifies the campaign medium.
func (h *Client) CampaignMedium(campaignMedium string) *Client {
	h.campaignMedium = campaignMedium
	h.campaignMediumSet = true
	return h
}

// Specifies the campaign keyword.
func (h *Client) CampaignKeyword(campaignKeyword string) *Client {
	h.campaignKeyword = campaignKeyword
	h.campaignKeywordSet = true
	return h
}

// Specifies the campaign content.
func (h *Client) CampaignContent(campaignContent string) *Client {
	h.campaignContent = campaignContent
	h.campaignContentSet = true
	return h
}

// Specifies the campaign ID.
func (h *Client) CampaignID(campaignID string) *Client {
	h.campaignID = campaignID
	h.campaignIDSet = true
	return h
}

// Specifies the Google AdWords Id.
func (h *Client) GoogleAdWordsID(googleAdWordsID string) *Client {
	h.googleAdWordsID = googleAdWordsID
	h.googleAdWordsIDSet = true
	return h
}

// Specifies the Google Display Ads Id.
func (h *Client) GoogleDisplayAdsID(googleDisplayAdsID string) *Client {
	h.googleDisplayAdsID = googleDisplayAdsID
	h.googleDisplayAdsIDSet = true
	return h
}

// Specifies the screen resolution.
func (h *Client) ScreenResolution(screenResolution string) *Client {
	h.screenResolution = screenResolution
	h.screenResolutionSet = true
	return h
}

// Specifies the viewable area of the browser / device.
func (h *Client) ViewportSize(viewportSize string) *Client {
	h.viewportSize = viewportSize
	h.viewportSizeSet = true
	return h
}

// Specifies the character set used to encode the page / document.
func (h *Client) DocumentEncoding(documentEncoding string) *Client {
	h.documentEncoding = documentEncoding
	h.documentEncodingSet = true
	return h
}

// Specifies the screen color depth.
func (h *Client) ScreenColors(screenColors string) *Client {
	h.screenColors = screenColors
	h.screenColorsSet = true
	return h
}

// Specifies the language.
func (h *Client) UserLanguage(userLanguage string) *Client {
	h.userLanguage = userLanguage
	h.userLanguageSet = true
	return h
}

// Specifies whether Java was enabled.
func (h *Client) JavaEnabled(javaEnabled bool) *Client {
	h.javaEnabled = javaEnabled
	h.javaEnabledSet = true
	return h
}

// Specifies the flash version.
func (h *Client) FlashVersion(flashVersion string) *Client {
	h.flashVersion = flashVersion
	h.flashVersionSet = true
	return h
}

// Specifies that a hit be considered non-interactive.
func (h *Client) NonInteractionHit(nonInteractionHit bool) *Client {
	h.nonInteractionHit = nonInteractionHit
	h.nonInteractionHitSet = true
	return h
}

// Use this parameter to send the full URL (document location)
// of the page on which content resides. You can use the &dh
// and &dp parameters to override the hostname and path + query
// portions of the document location, accordingly. The JavaScript
// clients determine this parameter using the concatenation
// of the document.location.origin + document.location.pathname
// + document.location.search browser parameters. Be sure to
// remove any user authentication or other private information
// from the URL if present. For 'pageview' hits, either &dl
// or both &dh and &dp have to be specified for the hit to
// be valid.
func (h *Client) DocumentLocationURL(documentLocationURL string) *Client {
	h.documentLocationURL = documentLocationURL
	h.documentLocationURLSet = true
	return h
}

// Specifies the hostname from which content was hosted.
func (h *Client) DocumentHostName(documentHostName string) *Client {
	h.documentHostName = documentHostName
	h.documentHostNameSet = true
	return h
}

// The path portion of the page URL. Should begin with '/'.
// For 'pageview' hits, either &dl or both &dh and &dp have
// to be specified for the hit to be valid.
func (h *Client) DocumentPath(documentPath string) *Client {
	h.documentPath = documentPath
	h.documentPathSet = true
	return h
}

// The title of the page / document.
func (h *Client) DocumentTitle(documentTitle string) *Client {
	h.documentTitle = documentTitle
	h.documentTitleSet = true
	return h
}

// If not specified, this will default to the unique URL of
// the page by either using the &dl parameter as-is or assembling
// it from &dh and &dp. App tracking makes use of this for
// the 'Screen Name' of the screenview hit.
func (h *Client) ScreenName(screenName string) *Client {
	h.screenName = screenName
	h.screenNameSet = true
	return h
}

// The ID of a clicked DOM element, used to disambiguate multiple
// links to the same URL in In-Page Analytics reports when
// Enhanced Link Attribution is enabled for the property.
func (h *Client) LinkID(linkID string) *Client {
	h.linkID = linkID
	h.linkIDSet = true
	return h
}

// Specifies the application name.
func (h *Client) ApplicationName(applicationName string) *Client {
	h.applicationName = applicationName
	h.applicationNameSet = true
	return h
}

// Application identifier.
func (h *Client) ApplicationID(applicationID string) *Client {
	h.applicationID = applicationID
	h.applicationIDSet = true
	return h
}

// Specifies the application version.
func (h *Client) ApplicationVersion(applicationVersion string) *Client {
	h.applicationVersion = applicationVersion
	h.applicationVersionSet = true
	return h
}

// Application installer identifier.
func (h *Client) ApplicationInstallerID(applicationInstallerID string) *Client {
	h.applicationInstallerID = applicationInstallerID
	h.applicationInstallerIDSet = true
	return h
}

// The SKU of the product. Product index must be a positive
// integer between 1 and 200, inclusive. For analytics.js the
// Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) ProductSKU(productSKU string) *Client {
	h.productSKU = productSKU
	h.productSKUSet = true
	return h
}

// The name of the product. Product index must be a positive
// integer between 1 and 200, inclusive. For analytics.js the
// Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) ProductName(productName string) *Client {
	h.productName = productName
	h.productNameSet = true
	return h
}

// The brand associated with the product. Product index must
// be a positive integer between 1 and 200, inclusive. For
// analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) ProductBrand(productBrand string) *Client {
	h.productBrand = productBrand
	h.productBrandSet = true
	return h
}

// The category to which the product belongs. Product index
// must be a positive integer between 1 and 200, inclusive.
// The product category parameter can be hierarchical. Use
// / as a delimiter to specify up to 5-levels of hierarchy.
// For analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) ProductCategory(productCategory string) *Client {
	h.productCategory = productCategory
	h.productCategorySet = true
	return h
}

// The variant of the product. Product index must be a positive
// integer between 1 and 200, inclusive. For analytics.js the
// Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) ProductVariant(productVariant string) *Client {
	h.productVariant = productVariant
	h.productVariantSet = true
	return h
}

// The price of a product. Product index must be a positive
// integer between 1 and 200, inclusive. For analytics.js the
// Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) ProductPrice(productPrice float64) *Client {
	h.productPrice = productPrice
	h.productPriceSet = true
	return h
}

// The quantity of a product. Product index must be a positive
// integer between 1 and 200, inclusive. For analytics.js the
// Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) ProductQuantity(productQuantity int64) *Client {
	h.productQuantity = productQuantity
	h.productQuantitySet = true
	return h
}

// The coupon code associated with a product. Product index
// must be a positive integer between 1 and 200, inclusive.
// For analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) ProductCouponCode(productCouponCode string) *Client {
	h.productCouponCode = productCouponCode
	h.productCouponCodeSet = true
	return h
}

// The product's position in a list or collection. Product
// index must be a positive integer between 1 and 200, inclusive.
// For analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) ProductPosition(productPosition int64) *Client {
	h.productPosition = productPosition
	h.productPositionSet = true
	return h
}

// A product-level custom dimension where dimension index is
// a positive integer between 1 and 200, inclusive. Product
// index must be a positive integer between 1 and 200, inclusive.
// For analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) ProductCustomDimension(productCustomDimension string) *Client {
	h.productCustomDimension = productCustomDimension
	h.productCustomDimensionSet = true
	return h
}

// A product-level custom metric where metric index is a positive
// integer between 1 and 200, inclusive. Product index must
// be a positive integer between 1 and 200, inclusive. For
// analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) ProductCustomMetric(productCustomMetric int64) *Client {
	h.productCustomMetric = productCustomMetric
	h.productCustomMetricSet = true
	return h
}

// The role of the products included in a hit. If a product
// action is not specified, all product definitions included
// with the hit will be ignored. Must be one of: detail, click,
// add, remove, checkout, checkout_option, purchase, refund.
// For analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) ProductAction(productAction string) *Client {
	h.productAction = productAction
	h.productActionSet = true
	return h
}

// The transaction ID. This is an additional parameter that
// can be sent when Product Action is set to 'purchase' or
// 'refund'. For analytics.js the Enhanced Ecommerce plugin
// must be installed before using this field.
func (h *Client) TransactionID(transactionID string) *Client {
	h.transactionID = transactionID
	h.transactionIDSet = true
	return h
}

// The store or affiliation from which this transaction occurred.
// This is an additional parameter that can be sent when Product
// Action is set to 'purchase' or 'refund'. For analytics.js
// the Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) Affiliation(affiliation string) *Client {
	h.affiliation = affiliation
	h.affiliationSet = true
	return h
}

// The total value of the transaction, including tax and shipping.
// If not sent, this value will be automatically calculated
// using the product quantity and price fields of all products
// in the same hit. This is an additional parameter that can
// be sent when Product Action is set to 'purchase' or 'refund'.
// For analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) Revenue(revenue float64) *Client {
	h.revenue = revenue
	h.revenueSet = true
	return h
}

// The total tax associated with the transaction. This is an
// additional parameter that can be sent when Product Action
// is set to 'purchase' or 'refund'. For analytics.js the Enhanced
// Ecommerce plugin must be installed before using this field.
func (h *Client) Tax(tax float64) *Client {
	h.tax = tax
	h.taxSet = true
	return h
}

// The shipping cost associated with the transaction. This
// is an additional parameter that can be sent when Product
// Action is set to 'purchase' or 'refund'. For analytics.js
// the Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) Shipping(shipping float64) *Client {
	h.shipping = shipping
	h.shippingSet = true
	return h
}

// The transaction coupon redeemed with the transaction. This
// is an additional parameter that can be sent when Product
// Action is set to 'purchase' or 'refund'. For analytics.js
// the Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) CouponCode(couponCode string) *Client {
	h.couponCode = couponCode
	h.couponCodeSet = true
	return h
}

// The list or collection from which a product action occurred.
// This is an additional parameter that can be sent when Product
// Action is set to 'detail' or 'click'. For analytics.js the
// Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) ProductActionList(productActionList string) *Client {
	h.productActionList = productActionList
	h.productActionListSet = true
	return h
}

// The step number in a checkout funnel. This is an additional
// parameter that can be sent when Product Action is set to
// 'checkout'. For analytics.js the Enhanced Ecommerce plugin
// must be installed before using this field.
func (h *Client) CheckoutStep(checkoutStep int64) *Client {
	h.checkoutStep = checkoutStep
	h.checkoutStepSet = true
	return h
}

// Additional information about a checkout step. This is an
// additional parameter that can be sent when Product Action
// is set to 'checkout'. For analytics.js the Enhanced Ecommerce
// plugin must be installed before using this field.
func (h *Client) CheckoutStepOption(checkoutStepOption string) *Client {
	h.checkoutStepOption = checkoutStepOption
	h.checkoutStepOptionSet = true
	return h
}

// The list or collection to which a product belongs. Impression
// List index must be a positive integer between 1 and 200,
// inclusive. For analytics.js the Enhanced Ecommerce plugin
// must be installed before using this field.
func (h *Client) ProductImpressionListName(productImpressionListName string) *Client {
	h.productImpressionListName = productImpressionListName
	h.productImpressionListNameSet = true
	return h
}

// The product ID or SKU. Impression List index must be a positive
// integer between 1 and 200, inclusive. Product index must
// be a positive integer between 1 and 200, inclusive. For
// analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) ProductImpressionSKU(productImpressionSKU string) *Client {
	h.productImpressionSKU = productImpressionSKU
	h.productImpressionSKUSet = true
	return h
}

// The name of the product. Impression List index must be a
// positive integer between 1 and 200, inclusive. Product index
// must be a positive integer between 1 and 200, inclusive.
// For analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) ProductImpressionName(productImpressionName string) *Client {
	h.productImpressionName = productImpressionName
	h.productImpressionNameSet = true
	return h
}

// The brand associated with the product. Impression List index
// must be a positive integer between 1 and 200, inclusive.
// Product index must be a positive integer between 1 and 200,
// inclusive. For analytics.js the Enhanced Ecommerce plugin
// must be installed before using this field.
func (h *Client) ProductImpressionBrand(productImpressionBrand string) *Client {
	h.productImpressionBrand = productImpressionBrand
	h.productImpressionBrandSet = true
	return h
}

// The category to which the product belongs. Impression List
// index must be a positive integer between 1 and 200, inclusive.
// Product index must be a positive integer between 1 and 200,
// inclusive. For analytics.js the Enhanced Ecommerce plugin
// must be installed before using this field.
func (h *Client) ProductImpressionCategory(productImpressionCategory string) *Client {
	h.productImpressionCategory = productImpressionCategory
	h.productImpressionCategorySet = true
	return h
}

// The variant of the product. Impression List index must be
// a positive integer between 1 and 200, inclusive. Product
// index must be a positive integer between 1 and 200, inclusive.
// For analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) ProductImpressionVariant(productImpressionVariant string) *Client {
	h.productImpressionVariant = productImpressionVariant
	h.productImpressionVariantSet = true
	return h
}

// The product's position in a list or collection. Impression
// List index must be a positive integer between 1 and 200,
// inclusive. Product index must be a positive integer between
// 1 and 200, inclusive. For analytics.js the Enhanced Ecommerce
// plugin must be installed before using this field.
func (h *Client) ProductImpressionPosition(productImpressionPosition int64) *Client {
	h.productImpressionPosition = productImpressionPosition
	h.productImpressionPositionSet = true
	return h
}

// The price of a product. Impression List index must be a
// positive integer between 1 and 200, inclusive. Product index
// must be a positive integer between 1 and 200, inclusive.
// For analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) ProductImpressionPrice(productImpressionPrice float64) *Client {
	h.productImpressionPrice = productImpressionPrice
	h.productImpressionPriceSet = true
	return h
}

// A product-level custom dimension where dimension index is
// a positive integer between 1 and 200, inclusive. Impression
// List index must be a positive integer between 1 and 200,
// inclusive. Product index must be a positive integer between
// 1 and 200, inclusive. For analytics.js the Enhanced Ecommerce
// plugin must be installed before using this field.
func (h *Client) ProductImpressionCustomDimension(productImpressionCustomDimension string) *Client {
	h.productImpressionCustomDimension = productImpressionCustomDimension
	h.productImpressionCustomDimensionSet = true
	return h
}

// A product-level custom metric where metric index is a positive
// integer between 1 and 200, inclusive. Impression List index
// must be a positive integer between 1 and 200, inclusive.
// Product index must be a positive integer between 1 and 200,
// inclusive. For analytics.js the Enhanced Ecommerce plugin
// must be installed before using this field.
func (h *Client) ProductImpressionCustomMetric(productImpressionCustomMetric int64) *Client {
	h.productImpressionCustomMetric = productImpressionCustomMetric
	h.productImpressionCustomMetricSet = true
	return h
}

// The promotion ID. Promotion index must be a positive integer
// between 1 and 200, inclusive. For analytics.js the Enhanced
// Ecommerce plugin must be installed before using this field.
func (h *Client) PromotionID(promotionID string) *Client {
	h.promotionID = promotionID
	h.promotionIDSet = true
	return h
}

// The name of the promotion. Promotion index must be a positive
// integer between 1 and 200, inclusive. For analytics.js the
// Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) PromotionName(promotionName string) *Client {
	h.promotionName = promotionName
	h.promotionNameSet = true
	return h
}

// The creative associated with the promotion. Promotion index
// must be a positive integer between 1 and 200, inclusive.
// For analytics.js the Enhanced Ecommerce plugin must be installed
// before using this field.
func (h *Client) PromotionCreative(promotionCreative string) *Client {
	h.promotionCreative = promotionCreative
	h.promotionCreativeSet = true
	return h
}

// The position of the creative. Promotion index must be a
// positive integer between 1 and 200, inclusive. For analytics.js
// the Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) PromotionPosition(promotionPosition string) *Client {
	h.promotionPosition = promotionPosition
	h.promotionPositionSet = true
	return h
}

// Specifies the role of the promotions included in a hit.
// If a promotion action is not specified, the default promotion
// action, 'view', is assumed. To measure a user click on a
// promotion set this to 'promo_click'. For analytics.js the
// Enhanced Ecommerce plugin must be installed before using
// this field.
func (h *Client) PromotionAction(promotionAction string) *Client {
	h.promotionAction = promotionAction
	h.promotionActionSet = true
	return h
}

// Each custom dimension has an associated index. There is
// a maximum of 20 custom dimensions (200 for Premium accounts).
// The dimension index must be a positive integer between 1
// and 200, inclusive.
func (h *Client) CustomDimension(customDimension string) *Client {
	h.customDimension = customDimension
	h.customDimensionSet = true
	return h
}

// Each custom metric has an associated index. There is a maximum
// of 20 custom metrics (200 for Premium accounts). The metric
// index must be a positive integer between 1 and 200, inclusive.
func (h *Client) CustomMetric(customMetric int64) *Client {
	h.customMetric = customMetric
	h.customMetricSet = true
	return h
}

// This parameter specifies that this user has been exposed
// to an experiment with the given ID. It should be sent in
// conjunction with the Experiment Variant parameter.
func (h *Client) ExperimentID(experimentID string) *Client {
	h.experimentID = experimentID
	h.experimentIDSet = true
	return h
}

// This parameter specifies that this user has been exposed
// to a particular variation of an experiment. It should be
// sent in conjunction with the Experiment ID parameter.
func (h *Client) ExperimentVariant(experimentVariant string) *Client {
	h.experimentVariant = experimentVariant
	h.experimentVariantSet = true
	return h
}

// DimensionIndex is required by other properties
func (h *Client) DimensionIndex(dimensionIndex string) *Client {
	h.dimensionIndex = dimensionIndex
	h.dimensionIndexSet = true
	return h
}

// ListIndex is required by other properties
func (h *Client) ListIndex(listIndex string) *Client {
	h.listIndex = listIndex
	h.listIndexSet = true
	return h
}

// MetricIndex is required by other properties
func (h *Client) MetricIndex(metricIndex string) *Client {
	h.metricIndex = metricIndex
	h.metricIndexSet = true
	return h
}

// ProductIndex is required by other properties
func (h *Client) ProductIndex(productIndex string) *Client {
	h.productIndex = productIndex
	h.productIndexSet = true
	return h
}

// PromoIndex is required by other properties
func (h *Client) PromoIndex(promoIndex string) *Client {
	h.promoIndex = promoIndex
	h.promoIndexSet = true
	return h
}

func (h *Client) Copy() *Client {
	c := *h
	return &c
}
