diff --git a/integration/watermill/gtm/publisher.go b/integration/watermill/gtm/publisher.go index 5dbf98f..6d3feb8 100644 --- a/integration/watermill/gtm/publisher.go +++ b/integration/watermill/gtm/publisher.go @@ -79,25 +79,12 @@ func (p *Publisher) Publish(topic string, messages ...*message.Message) error { return err } - values, body, err := mpv2.Marshal(event) + values, body, err := mpv2.Encode(event) if err != nil { return err } - // NOTE: `richsstsse` seems to be last parameter in the query to let's ensure it stays that way - var richsstsse bool - if values.Has("richsstsse") { - richsstsse = true - values.Del("richsstsse") - } - - url := fmt.Sprintf("%s?%s", p.url, values.Encode()) - - if richsstsse { - url += "&richsstsse" - } - - req, err := http.NewRequestWithContext(msg.Context(), http.MethodPost, url, body) + req, err := http.NewRequestWithContext(msg.Context(), http.MethodPost, fmt.Sprintf("%s?%s", p.url, mpv2.EncodeValues(values)), body) if err != nil { return errors.Wrap(err, "failed to create request") } diff --git a/integration/watermill/keel/subscriber.go b/integration/watermill/keel/subscriber.go index d14a949..7d06778 100644 --- a/integration/watermill/keel/subscriber.go +++ b/integration/watermill/keel/subscriber.go @@ -138,7 +138,7 @@ func (s *Subscriber) ServeHTTP(w http.ResponseWriter, r *http.Request) { // unmarshal event var event *mpv2.Event - if err := mpv2.UnmarshalURLValues(values, &event); err != nil { + if err := mpv2.Decode(values, &event); err != nil { keelhttputils.InternalServerError(l, w, r, errors.Wrap(err, "failed to marshal url values")) return } diff --git a/measurementprotocol/v2/client.go b/measurementprotocol/v2/client.go index 25bcca8..32db1c1 100644 --- a/measurementprotocol/v2/client.go +++ b/measurementprotocol/v2/client.go @@ -1,6 +1,7 @@ package v2 import ( + "fmt" "io" "net/http" "net/url" @@ -129,7 +130,7 @@ func (c *Client) Send(r *http.Request, event *Event) error { } func (c *Client) SendRaw(r *http.Request, event *Event) error { - values, body, err := Marshal(event) + values, body, err := Encode(event) if err != nil { return errors.Wrap(err, "failed to marshall event") } @@ -137,7 +138,7 @@ func (c *Client) SendRaw(r *http.Request, event *Event) error { req, err := http.NewRequestWithContext( r.Context(), http.MethodPost, - c.url+"?"+values.Encode(), + fmt.Sprintf("%s?%s", c.url, EncodeValues(values)), body, ) if err != nil { diff --git a/measurementprotocol/v2/contants.go b/measurementprotocol/v2/contants.go new file mode 100644 index 0000000..7ffcac3 --- /dev/null +++ b/measurementprotocol/v2/contants.go @@ -0,0 +1,13 @@ +package v2 + +import ( + "regexp" +) + +var ( + RegexProduct = regexp.MustCompile(`pr([1-9]|[1-9][0-9]|1[0-9]{2}|200)`) +) + +const ( + ParameterItem = "pr" +) diff --git a/measurementprotocol/v2/data.go b/measurementprotocol/v2/data.go new file mode 100644 index 0000000..7e491aa --- /dev/null +++ b/measurementprotocol/v2/data.go @@ -0,0 +1,3 @@ +package v2 + +type Data map[string]any diff --git a/measurementprotocol/v2/decode.go b/measurementprotocol/v2/decode.go new file mode 100644 index 0000000..987a3bc --- /dev/null +++ b/measurementprotocol/v2/decode.go @@ -0,0 +1,98 @@ +package v2 + +import ( + "net/url" + "regexp" + "strings" + + "github.com/mitchellh/mapstructure" + "github.com/pkg/errors" +) + +func Decode(input url.Values, output interface{}) error { + data := Data{} + + // decode values + for k, v := range input { + // handle maps + if ok, err := DecodeMapValue(k, v, data); err != nil { + return err + } else if ok { + continue + } + + // handle slices + if ok, err := DecodeRegexValue(k, v, RegexProduct, data, ParameterItem); err != nil { + return err + } else if ok { + continue + } + + // default + v, err := url.QueryUnescape(v[0]) + if err != nil { + return err + } + data[k] = v + } + + if err := mapstructure.WeakDecode(data, output); err != nil { + return errors.Wrap(err, "failed to weakly decode query") + } + + return nil +} + +func DecodeMapValue(k string, v []string, data Data) (bool, error) { + if strings.Contains(k, ".") { + parts := strings.Split(k, ".") + if _, ok := data[parts[0]]; !ok { + data[parts[0]] = map[string]any{} + } + if value, ok := data[parts[0]].(map[string]any); ok { + v, err := url.QueryUnescape(v[0]) + if err != nil { + return false, err + } + value[strings.Join(parts[1:], ".")] = v + } + return true, nil + } + return false, nil +} + +// DecodeRegexValue e.g. `pr1=idSKU_123456` = map["pr"][]map["id"]="SKU_123456" +func DecodeRegexValue(k string, v []string, r *regexp.Regexp, data Data, key string) (bool, error) { + if r.MatchString(k) { + value, err := DecodeObjectValue(v[0]) + if err != nil { + return false, err + } + if value != nil { + v, ok := data[key].([]map[string]any) + if !ok { + v = []map[string]any{} + } + v = append(v, value) + data[key] = v + return true, nil + } + } + return false, nil +} + +// DecodeObjectValue e.g. `idSKU_123456` = map["id"]="SKU_123456" +func DecodeObjectValue(s string) (map[string]any, error) { + if len(s) == 0 { + return nil, nil //nolint:nilnil + } + ret := map[string]any{} + for _, part := range strings.Split(s, "~") { + v, err := url.QueryUnescape(part[2:]) + if err != nil { + return nil, err + } + ret[part[0:2]] = v + } + return ret, nil +} diff --git a/measurementprotocol/v2/unmarshal_test.go b/measurementprotocol/v2/decode_test.go similarity index 62% rename from measurementprotocol/v2/unmarshal_test.go rename to measurementprotocol/v2/decode_test.go index e4d6442..ced1cde 100644 --- a/measurementprotocol/v2/unmarshal_test.go +++ b/measurementprotocol/v2/decode_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestUnmarshalURLValues(t *testing.T) { +func TestDecode(t *testing.T) { tests := []struct { name string args string @@ -32,48 +32,15 @@ func TestUnmarshalURLValues(t *testing.T) { u, err := url.ParseQuery(tt.args) require.NoError(t, err) e := &mpv2.Event{} - if err := mpv2.UnmarshalURLValues(u, e); !assert.ErrorIs(t, err, tt.want) { - t.Errorf("UnmarshalURLValues() = %v, want %v", err, tt.want) + if err := mpv2.Decode(u, e); !assert.ErrorIs(t, err, tt.want) { + t.Errorf("Decode() = %v, want %v", err, tt.want) t.Log(e) } }) } } -func TestMarshalURLValues(t *testing.T) { - tests := []struct { - name string - args string - want error - }{ - { - name: "page_view", - args: "v=2&tid=G-123456>m=45je42s0v893689383z8894072534za200&_p=1709286636310&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=292234677.1707898933&ul=en-us&sr=3840x1600&uaa=arm&uab=64&uafvl=Chromium&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pae=1&pscdl=noapi&_s=1&sid=1709286452&sct=7&seg=1&dl=https%3A%2F%2Fwww.homemade.ch%2Fprodukt%2Fkuhn-rikon-wiegemesser-900047100%3Fid%3D900047100&dr=https%3A%2F%2Fwww.homemade.ch%2Fmesser-besteck&dt=Wiegemesser&en=page_view&tfd=5682", - want: nil, - }, - //{ - // name: "add_to_cart", - // args: "v=2&tid=G-123456>m=45je42s0v9175354889z89175348963za200&_p=1709297934217&_dbg=1&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=DE-BY&uaa=arm&uab=64&uafvl=Chromium&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=DE&sst.etld=google.de&sst.gcsub=region1&sst.gcd=13l3l3l3l1&sst.tft=1709297934217&_s=8&cu=USD&sid=1709296380&sct=7&seg=1&dl=https%3A%2F%2Fsniffer.cloud.bestbytes.net%2F%3Fgtm_debug%3D1709297933868&dr=https%3A%2F%2Ftagassistant.google.com%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=add_to_cart&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&tfd=15129&richsstsse", - // want: nil, - // }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - u, err := url.ParseQuery(tt.args) - require.NoError(t, err) - e := &mpv2.Event{} - require.NoError(t, mpv2.UnmarshalURLValues(u, e)) - if !assert.Empty(t, e.Unknown) { - t.Errorf("MarshalURLValues() = %v, want %v", e.Unknown, nil) - } - if out, _, err := mpv2.Marshal(e); assert.NoError(t, err) { - assert.EqualValues(t, u, out) - } - }) - } -} - -func TestCollect_decodeMapValue(t *testing.T) { +func TestDecodeMapValue(t *testing.T) { tests := []struct { name string args string @@ -99,7 +66,7 @@ func TestCollect_decodeMapValue(t *testing.T) { require.NoError(t, err) for k, v := range values { if got, err := mpv2.DecodeMapValue(k, v, d); assert.NoError(t, err) && got != tt.want { - t.Errorf("decodeMapValue() = %v, want %v", got, tt.want) + t.Errorf("DecodeMapValue() = %v, want %v", got, tt.want) t.Log(d) } } diff --git a/measurementprotocol/v2/encode.go b/measurementprotocol/v2/encode.go new file mode 100644 index 0000000..d276da2 --- /dev/null +++ b/measurementprotocol/v2/encode.go @@ -0,0 +1,102 @@ +package v2 + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/url" + "sort" + "strings" + + "github.com/pkg/errors" +) + +func Encode(input *Event) (url.Values, io.Reader, error) { + var richsstsse bool + // NOTE: `richsstsse` seems to be last parameter in the query to let's ensure it stays that way + if input.Richsstsse != nil { + richsstsse = true + input.Richsstsse = nil + } + + a, err := json.Marshal(input) + if err != nil { + return nil, nil, err + } + + data := Data{} + if err := json.Unmarshal(a, &data); err != nil { + return nil, nil, errors.Wrap(err, "failed to decode into map") + } + + ret := url.Values{} + for k, v := range data { + switch t := v.(type) { + case []interface{}: + for key, value := range t { + switch tt := value.(type) { + case map[string]interface{}: + ret[fmt.Sprintf("%s%d", k, key+1)] = []string{EncodeObjectValue(tt)} + default: + panic("unhandled") + } + } + case map[string]string: + for key, value := range t { + ret[fmt.Sprintf("%s.%s", k, key)] = []string{value} + } + case map[string]interface{}: + for key, value := range t { + ret[fmt.Sprintf("%s.%s", k, key)] = []string{fmt.Sprintf("%v", value)} + } + case *string: + ret[k] = []string{*t} + case string: + ret[k] = []string{t} + default: + panic("unhandled") + } + } + + var body []string + var reader io.Reader + maxQueryLength := 2048 // + if richsstsse { + maxQueryLength -= len("&richsstsse") + } + for len(ret.Encode()) > maxQueryLength { + for s, i := range ret { + ret.Del(s) + body = append(body, s+"="+i[0]) + break + } + } + + if richsstsse { + ret.Add("richsstsse", "") + } + + if len(body) > 0 { + reader = bytes.NewReader([]byte(strings.Join(body, "&"))) + } + + return ret, reader, nil +} + +// EncodeObjectValue e.g. `idSKU_123456` = map["id"]="SKU_123456" +func EncodeObjectValue(s map[string]any) string { + if len(s) == 0 { + return "" + } + keys := make([]string, 0, len(s)) + for k := range s { + keys = append(keys, k) + } + sort.Strings(keys) + ret := make([]string, 0, len(keys)) + for _, k := range keys { + ret = append(ret, k+fmt.Sprintf("%s", s[k])) + } + return strings.Join(ret, "~") +} diff --git a/measurementprotocol/v2/encode_test.go b/measurementprotocol/v2/encode_test.go new file mode 100644 index 0000000..568a4de --- /dev/null +++ b/measurementprotocol/v2/encode_test.go @@ -0,0 +1,43 @@ +package v2_test + +import ( + "net/url" + "testing" + + mpv2 "github.com/foomo/sesamy-go/measurementprotocol/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestEncode(t *testing.T) { + tests := []struct { + name string + args string + want error + }{ + { + name: "page_view", + args: "v=2&tid=G-123456>m=45je42s0v893689383z8894072534za200&_p=1709286636310&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=292234677.1707898933&ul=en-us&sr=3840x1600&uaa=arm&uab=64&uafvl=Chromium&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pae=1&pscdl=noapi&_s=1&sid=1709286452&sct=7&seg=1&dl=https%3A%2F%2Fwww.homemade.ch%2Fprodukt%2Fkuhn-rikon-wiegemesser-900047100%3Fid%3D900047100&dr=https%3A%2F%2Fwww.homemade.ch%2Fmesser-besteck&dt=Wiegemesser&en=page_view&tfd=5682", + want: nil, + }, + // { + // name: "add_to_cart", + // args: "v=2&tid=G-123456>m=45je42s0v9175354889z89175348963za200&_p=1709297934217&_dbg=1&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=DE-BY&uaa=arm&uab=64&uafvl=Chromium&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=DE&sst.etld=google.de&sst.gcsub=region1&sst.gcd=13l3l3l3l1&sst.tft=1709297934217&_s=8&cu=USD&sid=1709296380&sct=7&seg=1&dl=https%3A%2F%2Fsniffer.cloud.bestbytes.net%2F%3Fgtm_debug%3D1709297933868&dr=https%3A%2F%2Ftagassistant.google.com%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=add_to_cart&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&tfd=15129&richsstsse", + // want: nil, + // }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u, err := url.ParseQuery(tt.args) + require.NoError(t, err) + e := &mpv2.Event{} + require.NoError(t, mpv2.Decode(u, e)) + if !assert.Empty(t, e.Unknown) { + t.Errorf("Encode() = %v, want %v", e.Unknown, nil) + } + if out, _, err := mpv2.Encode(e); assert.NoError(t, err) { + assert.EqualValues(t, u, out) + } + }) + } +} diff --git a/measurementprotocol/v2/event/addpaymentinfo.go b/measurementprotocol/v2/event/addpaymentinfo.go index 5ab15b3..645d9e6 100644 --- a/measurementprotocol/v2/event/addpaymentinfo.go +++ b/measurementprotocol/v2/event/addpaymentinfo.go @@ -40,17 +40,17 @@ AddPaymentInfo https://developers.google.com/tag-platform/gtagjs/reference/event Query: v=2&tid=G-123456>m=45je42t1v9177778896z89175355532za200&_p=1709325262551&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=DE-BY&uaa=arm&uab=64&uafvl=Chromium%3B122.0.6261.69%7CNot(A%253ABrand%3B24.0.0.0%7CGoogle%2520Chrome%3B122.0.6261.69&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=DE&sst.etld=google.de&sst.gcsub=region1&sst.gcd=13l3l3l3l1&sst.tft=1709325262551&_s=5&cu=USD&sid=1709445696&sct=8&seg=0&dl=https%3A%2F%2Fsniffer.local.bestbytes.net%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=add_payment_info&_ss=1&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&ep.coupon=SUMMER_FUN&ep.payment_type=Credit%20Card&tfd=120434230&richsstsse */ type AddPaymentInfo struct { - Currency string - Value float64 - Coupon string - PaymentType string - Items []*Item + Currency string `json:"currency,omitempty"` + Value float64 `json:"value,omitempty"` + Coupon string `json:"coupon,omitempty"` + PaymentType string `json:"payment_type,omitempty"` + Items []*Item `json:"items,omitempty"` } -func (e *AddPaymentInfo) MPv2() *mpv2.Event { +func (e *AddPaymentInfo) MarshalMPv2() (*mpv2.Event, error) { items := make([]*mpv2.Item, len(e.Items)) for i, item := range e.Items { - items[i] = item.MPv2() + items[i] = item.MarshalMPv2() } eventParameter := map[string]string{} mp.AddStringMap(eventParameter, mpv2.EventParameterCoupon.String(), mp.SetString(e.Coupon)) @@ -63,5 +63,5 @@ func (e *AddPaymentInfo) MPv2() *mpv2.Event { EventParameter: mp.SetStringMap(eventParameter), EventParameterNumber: mp.SetStringMap(eventParameterNumber), Items: items, - } + }, nil } diff --git a/measurementprotocol/v2/event/addshippinginfo.go b/measurementprotocol/v2/event/addshippinginfo.go index d97746d..ce34975 100644 --- a/measurementprotocol/v2/event/addshippinginfo.go +++ b/measurementprotocol/v2/event/addshippinginfo.go @@ -40,17 +40,17 @@ AddShippingInfo https://developers.google.com/tag-platform/gtagjs/reference/even Query: v=2&tid=G-PZ5ELRCR31>m=45je42t1v9177778896z89175355532za220&_p=1709357665402&_dbg=1&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=DE-BY&uaa=arm&uab=64&uafvl=Chromium%3B122.0.6261.69%7CNot(A%253ABrand%3B24.0.0.0%7CGoogle%2520Chrome%3B122.0.6261.69&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=DE&sst.etld=google.de&sst.gcsub=region1&sst.gcd=13l3l3l3l1&sst.tft=1709357665402&_s=10&cu=USD&sid=1709529821&sct=9&seg=0&dl=https%3A%2F%2Fsniffer.local.bestbytes.net%2F%3Fgtm_debug%3D1709357665301&dr=https%3A%2F%2Ftagassistant.google.com%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=add_payment_info&_ss=1&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&ep.coupon=SUMMER_FUN&ep.shipping_tier=Ground&tfd=137238301&richsstsse */ type AddShippingInfo struct { - Currency string - Value float64 - Coupon string - ShippingTier string - Items []*Item + Currency string `json:"currency,omitempty"` + Value float64 `json:"value,omitempty"` + Coupon string `json:"coupon,omitempty"` + ShippingTier string `json:"shipping_tier,omitempty"` + Items []*Item `json:"items,omitempty"` } -func (e *AddShippingInfo) MPv2() *mpv2.Event { +func (e *AddShippingInfo) MarshalMPv2() (*mpv2.Event, error) { items := make([]*mpv2.Item, len(e.Items)) for i, item := range e.Items { - items[i] = item.MPv2() + items[i] = item.MarshalMPv2() } eventParameter := map[string]string{} mp.AddStringMap(eventParameter, mpv2.EventParameterCoupon.String(), mp.SetString(e.Coupon)) @@ -63,5 +63,5 @@ func (e *AddShippingInfo) MPv2() *mpv2.Event { EventParameter: mp.SetStringMap(eventParameter), EventParameterNumber: mp.SetStringMap(eventParameterNumber), Items: items, - } + }, nil } diff --git a/measurementprotocol/v2/event/addtocart.go b/measurementprotocol/v2/event/addtocart.go index 9a58c82..44419c8 100644 --- a/measurementprotocol/v2/event/addtocart.go +++ b/measurementprotocol/v2/event/addtocart.go @@ -38,15 +38,15 @@ AddToCart https://developers.google.com/tag-platform/gtagjs/reference/events#add Query: v=2&tid=G-PZ5ELRCR31>m=45je42t1v9177778896z89175355532za200&_p=1709325262551&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=DE-BY&uaa=arm&uab=64&uafvl=Chromium%3B122.0.6261.69%7CNot(A%253ABrand%3B24.0.0.0%7CGoogle%2520Chrome%3B122.0.6261.69&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=DE&sst.etld=google.de&sst.gcsub=region1&sst.gcd=13l3l3l3l1&sst.tft=1709325262551&_s=3&cu=USD&sid=1709324719&sct=6&seg=1&dl=https%3A%2F%2Fsniffer.local.bestbytes.net%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=add_to_cart&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&_et=3187&tfd=11387&richsstsse */ type AddToCart struct { - Currency string - Value float64 - Items []*Item + Currency string `json:"currency,omitempty"` + Value float64 `json:"value,omitempty"` + Items []*Item `json:"items,omitempty"` } -func (e *AddToCart) MPv2() *mpv2.Event { +func (e *AddToCart) MarshalMPv2() (*mpv2.Event, error) { items := make([]*mpv2.Item, len(e.Items)) for i, item := range e.Items { - items[i] = item.MPv2() + items[i] = item.MarshalMPv2() } eventParameterNumber := map[string]string{} mp.AddStringMap(eventParameterNumber, mpv2.EventParameterNumberValue.String(), mp.SetFloat64(e.Value)) @@ -56,5 +56,5 @@ func (e *AddToCart) MPv2() *mpv2.Event { EventParameterNumber: mp.SetStringMap(eventParameterNumber), Items: items, Richsstsse: mp.Set(""), - } + }, nil } diff --git a/measurementprotocol/v2/event/addtowishlist.go b/measurementprotocol/v2/event/addtowishlist.go index 3d6b247..6370ffd 100644 --- a/measurementprotocol/v2/event/addtowishlist.go +++ b/measurementprotocol/v2/event/addtowishlist.go @@ -38,15 +38,15 @@ AddToWishlist https://developers.google.com/tag-platform/gtagjs/reference/events Query: v=2&tid=G-PZ5ELRCR31>m=45je42t1v9177778896z89175355532za200&_p=1709325262551&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=DE-BY&uaa=arm&uab=64&uafvl=Chromium%3B122.0.6261.69%7CNot(A%253ABrand%3B24.0.0.0%7CGoogle%2520Chrome%3B122.0.6261.69&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=DE&sst.etld=google.de&sst.gcsub=region1&sst.gcd=13l3l3l3l1&sst.tft=1709325262551&_s=3&cu=USD&sid=1709324719&sct=6&seg=1&dl=https%3A%2F%2Fsniffer.local.bestbytes.net%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=add_to_wishlist&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&_et=3187&tfd=11387&richsstsse */ type AddToWishlist struct { - Currency string - Value float64 - Items []*Item + Currency string `json:"currency,omitempty"` + Value float64 `json:"value,omitempty"` + Items []*Item `json:"items,omitempty"` } -func (e *AddToWishlist) MPv2() *mpv2.Event { +func (e *AddToWishlist) MarshalMPv2() (*mpv2.Event, error) { items := make([]*mpv2.Item, len(e.Items)) for i, item := range e.Items { - items[i] = item.MPv2() + items[i] = item.MarshalMPv2() } eventParameterNumber := map[string]string{} mp.AddStringMap(eventParameterNumber, mpv2.EventParameterNumberValue.String(), mp.SetFloat64(e.Value)) @@ -55,5 +55,5 @@ func (e *AddToWishlist) MPv2() *mpv2.Event { Currency: mp.SetString(e.Currency), EventParameterNumber: mp.SetStringMap(eventParameterNumber), Items: items, - } + }, nil } diff --git a/measurementprotocol/v2/event/begincheckout.go b/measurementprotocol/v2/event/begincheckout.go index f0bbe21..cda867d 100644 --- a/measurementprotocol/v2/event/begincheckout.go +++ b/measurementprotocol/v2/event/begincheckout.go @@ -39,16 +39,16 @@ BeginCheckout https://developers.google.com/tag-platform/gtagjs/reference/events Query: v=2&tid=G-123456>m=45je42t1v9177778896z89175355532za200&_p=1709325262551&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=DE-BY&uaa=arm&uab=64&uafvl=Chromium%3B122.0.6261.69%7CNot(A%253ABrand%3B24.0.0.0%7CGoogle%2520Chrome%3B122.0.6261.69&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=DE&sst.etld=google.de&sst.gcsub=region1&sst.gcd=13l3l3l3l1&sst.tft=1709325262551&_s=5&cu=USD&sid=1709445696&sct=8&seg=0&dl=https%3A%2F%2Fsniffer.local.bestbytes.net%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=begin_checkout&_ss=1&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&ep.coupon=SUMMER_FUN&tfd=120434230&richsstsse */ type BeginCheckout struct { - Currency string - Value float64 - Coupon string - Items []*Item + Currency string `json:"currency,omitempty"` + Value float64 `json:"value,omitempty"` + Coupon string `json:"coupon,omitempty"` + Items []*Item `json:"items,omitempty"` } -func (e *BeginCheckout) MPv2() *mpv2.Event { +func (e *BeginCheckout) MarshalMPv2() (*mpv2.Event, error) { items := make([]*mpv2.Item, len(e.Items)) for i, item := range e.Items { - items[i] = item.MPv2() + items[i] = item.MarshalMPv2() } eventParameter := map[string]string{} mp.AddStringMap(eventParameter, mpv2.EventParameterCoupon.String(), mp.SetString(e.Coupon)) @@ -60,5 +60,5 @@ func (e *BeginCheckout) MPv2() *mpv2.Event { EventParameter: mp.SetStringMap(eventParameter), EventParameterNumber: mp.SetStringMap(eventParameterNumber), Items: items, - } + }, nil } diff --git a/measurementprotocol/v2/event/item.go b/measurementprotocol/v2/event/item.go index d25a4bf..ed8a118 100644 --- a/measurementprotocol/v2/event/item.go +++ b/measurementprotocol/v2/event/item.go @@ -6,43 +6,43 @@ import ( ) type Item struct { - ID string - Name string - Brand string - CategoryHierarchy1 string - CategoryHierarchy2 string - CategoryHierarchy3 string - CategoryHierarchy4 string - CategoryHierarchy5 string - Price string - Quantity float64 - Variant string - Coupon string - Discount float64 - Index int - ListName string - ListID string - Affiliation string - LocationID string + Affiliation string `json:"affiliation,omitempty"` + Coupon string `json:"coupon,omitempty"` + Discount float64 `json:"discount,omitempty"` + Index int `json:"index,omitempty"` + ItemBrand string `json:"item_brand,omitempty"` + ItemCategory string `json:"item_category,omitempty"` + ItemCategory2 string `json:"item_category2,omitempty"` + ItemCategory3 string `json:"item_category3,omitempty"` + ItemCategory4 string `json:"item_category4,omitempty"` + ItemCategory5 string `json:"item_category5,omitempty"` + ItemID string `json:"item_id,omitempty"` + ItemListName string `json:"item_list_name,omitempty"` + ItemName string `json:"item_name,omitempty"` + ItemVariant string `json:"item_variant,omitempty"` + ItemListID string `json:"listId,omitempty"` + LocationID string `json:"location_id,omitempty"` + Price string `json:"price,omitempty"` + Quantity float64 `json:"quantity,omitempty"` } -func (e *Item) MPv2() *mpv2.Item { +func (e *Item) MarshalMPv2() *mpv2.Item { return &mpv2.Item{ - ID: mp.SetString(e.ID), - Name: mp.SetString(e.Name), - Brand: mp.SetString(e.Brand), - CategoryHierarchy1: mp.SetString(e.CategoryHierarchy1), - CategoryHierarchy2: mp.SetString(e.CategoryHierarchy2), - CategoryHierarchy3: mp.SetString(e.CategoryHierarchy3), - CategoryHierarchy4: mp.SetString(e.CategoryHierarchy4), - CategoryHierarchy5: mp.SetString(e.CategoryHierarchy5), + ID: mp.SetString(e.ItemID), + Name: mp.SetString(e.ItemName), + Brand: mp.SetString(e.ItemBrand), + CategoryHierarchy1: mp.SetString(e.ItemCategory), + CategoryHierarchy2: mp.SetString(e.ItemCategory2), + CategoryHierarchy3: mp.SetString(e.ItemCategory3), + CategoryHierarchy4: mp.SetString(e.ItemCategory4), + CategoryHierarchy5: mp.SetString(e.ItemCategory5), Price: mp.SetString(e.Price), Quantity: mp.SetFloat64(e.Quantity), - Variant: mp.SetString(e.Variant), + Variant: mp.SetString(e.ItemVariant), Coupon: mp.SetString(e.Coupon), Discount: mp.SetFloat64(e.Discount), - ListName: mp.SetString(e.ListName), - ListID: mp.SetString(e.ListID), + ListName: mp.SetString(e.ItemListName), + ListID: mp.SetString(e.ItemListID), ListPosition: mp.SetInt(e.Index), Affiliation: mp.SetString(e.Affiliation), LocationID: mp.SetString(e.LocationID), diff --git a/measurementprotocol/v2/event/login.go b/measurementprotocol/v2/event/login.go index c151a92..e134db2 100644 --- a/measurementprotocol/v2/event/login.go +++ b/measurementprotocol/v2/event/login.go @@ -15,14 +15,14 @@ Login - Send this event to signify that a user has logged in to your website or Reference: https://developers.google.com/tag-platform/gtagjs/reference/events#login */ type Login struct { - Method string + Method string `json:"method,omitempty"` } -func (e *Login) MPv2() *mpv2.Event { +func (e *Login) MarshalMPv2() (*mpv2.Event, error) { eventParameter := map[string]string{} mp.AddStringMap(eventParameter, mpv2.EventParameterMethod.String(), mp.SetString(e.Method)) return &mpv2.Event{ EventName: mp.Set(mpv2.EventNameLogin), EventParameter: mp.SetStringMap(eventParameter), - } + }, nil } diff --git a/measurementprotocol/v2/event/purchase.go b/measurementprotocol/v2/event/purchase.go index a07c376..4d2fbdd 100644 --- a/measurementprotocol/v2/event/purchase.go +++ b/measurementprotocol/v2/event/purchase.go @@ -42,19 +42,19 @@ Purchase https://developers.google.com/tag-platform/gtagjs/reference/events#purc Query: v=2&tid=G-PZ5ELRCR31>m=45he42t1v9177778896z89175355532za220&_p=1709537217366&_dbg=1&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=&uaa=arm&uab=64&uafvl=Chromium%3B122.0.6261.69%7CNot(A%253ABrand%3B24.0.0.0%7CGoogle%2520Chrome%3B122.0.6261.69&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=&sst.gcd=13l3l3l3l1&sst.tft=1709537217366&_s=6&cu=USD&sid=1709534872&sct=10&seg=1&dl=https%3A%2F%2Fsniffer.local.bestbytes.net%2F%3Fgtm_debug%3D1709537217296&dr=https%3A%2F%2Ftagassistant.google.com%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=purchase&_c=1&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&ep.transaction_id=T_12345&ep.coupon=SUMMER_FUN&epn.shipping=3.33&epn.tax=1.11&tfd=184622&richsstsse */ type Purchase struct { - Currency string - Value float64 - TransactionID string - Coupon string - Shipping float64 - Tax float64 - Items []*Item + Currency string `json:"currency,omitempty"` + Value float64 `json:"value,omitempty"` + TransactionID string `json:"transaction_id,omitempty"` + Coupon string `json:"coupon,omitempty"` + Shipping float64 `json:"shipping,omitempty"` + Tax float64 `json:"tax,omitempty"` + Items []*Item `json:"items,omitempty"` } -func (e *Purchase) MPv2() *mpv2.Event { +func (e *Purchase) MarshalMPv2() (*mpv2.Event, error) { items := make([]*mpv2.Item, len(e.Items)) for i, item := range e.Items { - items[i] = item.MPv2() + items[i] = item.MarshalMPv2() } eventParameter := map[string]string{} mp.AddStringMap(eventParameter, mpv2.EventParameterTransactionID.String(), mp.SetString(e.TransactionID)) @@ -69,5 +69,5 @@ func (e *Purchase) MPv2() *mpv2.Event { EventParameter: mp.SetStringMap(eventParameter), EventParameterNumber: mp.SetStringMap(eventParameterNumber), Items: items, - } + }, nil } diff --git a/measurementprotocol/v2/event/refund.go b/measurementprotocol/v2/event/refund.go index a00bbeb..57a8dee 100644 --- a/measurementprotocol/v2/event/refund.go +++ b/measurementprotocol/v2/event/refund.go @@ -42,19 +42,19 @@ Refund https://developers.google.com/tag-platform/gtagjs/reference/events#refund Query: v=2&tid=G-PZ5ELRCR31>m=45he42t1v9177778896z89175355532za220&_p=1709537217366&_dbg=1&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=&uaa=arm&uab=64&uafvl=Chromium%3B122.0.6261.69%7CNot(A%253ABrand%3B24.0.0.0%7CGoogle%2520Chrome%3B122.0.6261.69&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=&sst.gcd=13l3l3l3l1&sst.tft=1709537217366&_s=6&cu=USD&sid=1709534872&sct=10&seg=1&dl=https%3A%2F%2Fsniffer.local.bestbytes.net%2F%3Fgtm_debug%3D1709537217296&dr=https%3A%2F%2Ftagassistant.google.com%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=refund&_c=1&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&ep.transaction_id=T_12345&ep.coupon=SUMMER_FUN&epn.shipping=3.33&epn.tax=1.11&tfd=184622&richsstsse */ type Refund struct { - Currency string - Value float64 - TransactionID string - Coupon string - Shipping float64 - Tax float64 - Items []*Item + Currency string `json:"currency,omitempty"` + Value float64 `json:"value,omitempty"` + TransactionID string `json:"transaction_id,omitempty"` + Coupon string `json:"coupon,omitempty"` + Shipping float64 `json:"shipping,omitempty"` + Tax float64 `json:"tax,omitempty"` + Items []*Item `json:"items,omitempty"` } -func (e *Refund) MPv2() *mpv2.Event { +func (e *Refund) MarshalMPv2() (*mpv2.Event, error) { items := make([]*mpv2.Item, len(e.Items)) for i, item := range e.Items { - items[i] = item.MPv2() + items[i] = item.MarshalMPv2() } eventParameter := map[string]string{} mp.AddStringMap(eventParameter, mpv2.EventParameterTransactionID.String(), mp.SetString(e.TransactionID)) @@ -69,5 +69,5 @@ func (e *Refund) MPv2() *mpv2.Event { EventParameter: mp.SetStringMap(eventParameter), EventParameterNumber: mp.SetStringMap(eventParameterNumber), Items: items, - } + }, nil } diff --git a/measurementprotocol/v2/event/removefromcart.go b/measurementprotocol/v2/event/removefromcart.go index 236b2ec..a50bf4d 100644 --- a/measurementprotocol/v2/event/removefromcart.go +++ b/measurementprotocol/v2/event/removefromcart.go @@ -38,15 +38,15 @@ RemoveFromCart https://developers.google.com/tag-platform/gtagjs/reference/event Query: v=2&tid=G-PZ5ELRCR31>m=45je42t1v9177778896z89175355532za200&_p=1709325262551&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=DE-BY&uaa=arm&uab=64&uafvl=Chromium%3B122.0.6261.69%7CNot(A%253ABrand%3B24.0.0.0%7CGoogle%2520Chrome%3B122.0.6261.69&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=DE&sst.etld=google.de&sst.gcsub=region1&sst.gcd=13l3l3l3l1&sst.tft=1709325262551&_s=3&cu=USD&sid=1709324719&sct=6&seg=1&dl=https%3A%2F%2Fsniffer.local.bestbytes.net%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=remove_from_cart&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&_et=3187&tfd=11387&richsstsse */ type RemoveFromCart struct { - Currency string - Value float64 - Items []*Item + Currency string `json:"currency,omitempty"` + Value float64 `json:"value,omitempty"` + Items []*Item `json:"items,omitempty"` } -func (e *RemoveFromCart) MPv2() *mpv2.Event { +func (e *RemoveFromCart) MarshalMPv2() (*mpv2.Event, error) { items := make([]*mpv2.Item, len(e.Items)) for i, item := range e.Items { - items[i] = item.MPv2() + items[i] = item.MarshalMPv2() } eventParameterNumber := map[string]string{} mp.AddStringMap(eventParameterNumber, mpv2.EventParameterNumberValue.String(), mp.SetFloat64(e.Value)) @@ -55,5 +55,5 @@ func (e *RemoveFromCart) MPv2() *mpv2.Event { Currency: mp.SetString(e.Currency), EventParameterNumber: mp.SetStringMap(eventParameterNumber), Items: items, - } + }, nil } diff --git a/measurementprotocol/v2/event/search.go b/measurementprotocol/v2/event/search.go index 5b7cedb..54b28ce 100644 --- a/measurementprotocol/v2/event/search.go +++ b/measurementprotocol/v2/event/search.go @@ -15,14 +15,14 @@ Search https://developers.google.com/tag-platform/gtagjs/reference/events#search Query: v=2&tid=G-PZ5ELRCR31>m=45je42t1v9177778896z89175355532za200&_p=1709325262551&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=DE-BY&uaa=arm&uab=64&uafvl=Chromium%3B122.0.6261.69%7CNot(A%253ABrand%3B24.0.0.0%7CGoogle%2520Chrome%3B122.0.6261.69&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=DE&sst.etld=google.de&sst.gcsub=region1&sst.gcd=13l3l3l3l1&sst.tft=1709325262551&_s=3&cu=USD&sid=1709324719&sct=6&seg=1&dl=https%3A%2F%2Fsniffer.local.bestbytes.net%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=search&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&_et=3187&tfd=11387&richsstsse */ type Search struct { - SearchTerm string + SearchTerm string `json:"search_term,omitempty"` } -func (e *Search) MPv2() *mpv2.Event { +func (e *Search) MarshalMPv2() (*mpv2.Event, error) { eventParameter := map[string]string{} mp.AddStringMap(eventParameter, mpv2.EventParameterSearchTerm.String(), mp.SetString(e.SearchTerm)) return &mpv2.Event{ EventName: mp.Set(mpv2.EventNameSearch), EventParameter: mp.SetStringMap(eventParameter), - } + }, nil } diff --git a/measurementprotocol/v2/event/signup.go b/measurementprotocol/v2/event/signup.go index aa3a075..9cb60d9 100644 --- a/measurementprotocol/v2/event/signup.go +++ b/measurementprotocol/v2/event/signup.go @@ -15,14 +15,14 @@ SignUp - Send this event to signify that a user has logged in to your website or Reference: https://developers.google.com/tag-platform/gtagjs/reference/events#sign_up */ type SignUp struct { - Method string + Method string `json:"method,omitempty"` } -func (e *SignUp) MPv2() *mpv2.Event { +func (e *SignUp) MarshalMPv2() (*mpv2.Event, error) { eventParameter := map[string]string{} mp.AddStringMap(eventParameter, mpv2.EventParameterMethod.String(), mp.SetString(e.Method)) return &mpv2.Event{ EventName: mp.Set(mpv2.EventNameSignUp), EventParameter: mp.SetStringMap(eventParameter), - } + }, nil } diff --git a/measurementprotocol/v2/eventparameter.go b/measurementprotocol/v2/eventparameter.go index 596847a..a162fe9 100644 --- a/measurementprotocol/v2/eventparameter.go +++ b/measurementprotocol/v2/eventparameter.go @@ -1,14 +1,162 @@ package v2 +// EventParameter as string +// See https://support.google.com/analytics/table/13594742?sjid=7861230991468479976-EU type EventParameter string const ( + // EventParameterAppVersion The mobile app's versionName (Android) or short bundle version (iOS) in which an event occurred + EventParameterAppVersion EventParameter = "app_version" + // EventParameterCancellationReason The reason a cancellation occurred + EventParameterCancellationReason EventParameter = "cancellation_reason" + // EventParameterFirebaseErrorValue Additional details corresponding to the error code reported by the Firebase SDK + EventParameterFirebaseErrorValue EventParameter = "firebase_error_value" + // EventParameterFirebaseScreen The current screen’s name, as provided by the developer + EventParameterFirebaseScreen EventParameter = "firebase_screen" + // EventParameterFirebaseScreenClass The current screen’s class name + EventParameterFirebaseScreenClass EventParameter = "firebase_screen_class" + // EventParameterFirebaseScreenId A random identifier for the current screen + EventParameterFirebaseScreenId EventParameter = "firebase_screen_id" + // EventParameterMessageId The Firebase Cloud Messaging or Firebase In-App Messaging message identifier, which is unique per message campaign + EventParameterMessageId EventParameter = "message_id" + // EventParameterMessageName The Firebase Cloud Messaging or Firebase In-App Messaging message name + EventParameterMessageName EventParameter = "message_name" + // EventParameterMessageType The Firebase Cloud Messaging message notification type + EventParameterMessageType EventParameter = "message_type" + // EventParameterPreviousAppVersion For the app_update event, the parameter signifies the previous application version + EventParameterPreviousAppVersion EventParameter = "previous_app_version" + // EventParameterPreviousOsVersion For the os_update event, the parameter signifies the previous OS version + EventParameterPreviousOsVersion EventParameter = "previous_os_version" + // EventParameterCampaignContent The ad content that was associated with the start of a session + EventParameterCampaignContent EventParameter = "campaign_content" + // EventParameterCampaignMedium The method for acquiring users to your website or application + EventParameterCampaignMedium EventParameter = "campaign_medium" + // EventParameterCampaignSource A representation of the publisher or inventory source from which traffic originated. For example, users who return to your website from Google Search show as "google" in the Session source dimension + EventParameterCampaignSource EventParameter = "campaign_source" + // EventParameterCampaignTerm The term that was associated with the start of a session + EventParameterCampaignTerm EventParameter = "campaign_term" + // EventParameterCoupon The coupon name or code associated with an event + EventParameterCoupon EventParameter = "coupon" + // EventParameterCurrency The currency used in an event, in 3-letter ISO 4217 format. For example, the currency used in a purchase + EventParameterCurrency EventParameter = "currency" + // EventParameterShippingTier The shipping tier selected for delivery of a purchased item + EventParameterShippingTier EventParameter = "shipping_tier" + // EventParameterTransactionId The unique identifier of a transaction + EventParameterTransactionId EventParameter = "transaction_id" + // EventParameterValue The monetary value of the event + EventParameterValue EventParameter = "value" + // EventParameterAffiliation A product affiliation to designate a supplying company or brick and mortar store location + EventParameterAffiliation EventParameter = "affiliation" + // EventParameterCreativeName The name of a creative used in a promotion. Example value: summer_banner + EventParameterCreativeName EventParameter = "creative_name" + // EventParameterCreativeSlot The name of the promotional creative slot associated with an event. Example value: featured_app_1 + EventParameterCreativeSlot EventParameter = "creative_slot" + // EventParameterDiscount The value of a discount value associated with a purchased item + EventParameterDiscount EventParameter = "discount" + // EventParameterIndex The index of the item in a list + EventParameterIndex EventParameter = "index" + // EventParameterItemBrand The brand of an item + EventParameterItemBrand EventParameter = "item_brand" + // EventParameterItemCategory The category of an item. If used as part of a category hierarchy or taxonomy, then this is the first category + EventParameterItemCategory EventParameter = "item_category" + // EventParameterItemCategory2 The second hierarchical category in which you classified an item + EventParameterItemCategory2 EventParameter = "item_category2" + // EventParameterItemCategory3 The third hierarchical category in which you classified an item + EventParameterItemCategory3 EventParameter = "item_category3" + // EventParameterItemCategory4 The fourth hierarchical category in which you classified an item + EventParameterItemCategory4 EventParameter = "Item_category4" + // EventParameterItemCategory5 The fifth hierarchical category in which you classified an item + EventParameterItemCategory5 EventParameter = "Item_category5" + // EventParameterItemId The ID that you specify for an item + EventParameterItemId EventParameter = "item_id" + // EventParameterItemListId The name of the list in which an item was presented to a user + EventParameterItemListId EventParameter = "item_list_id" + // EventParameterItemListName The ID of the list in which an item was presented to a user + EventParameterItemListName EventParameter = "item_list_name" + // EventParameterItemName The name of the event that contains the parameter group + EventParameterItemName EventParameter = "item_name" + // EventParameterItemVariant The item variant or unique code or description (e.g., XS, S, M, L for size; Red, Blue, Green, Black for color) for additional item details or options + EventParameterItemVariant EventParameter = "item_variant" + // EventParameterLocationId The physical location associated with the item (e.g. the physical store location) + EventParameterLocationId EventParameter = "location_id" + // EventParameterPromotionId The ID of the promotion associated with an event + EventParameterPromotionId EventParameter = "promotion_id" + // EventParameterPromotionName The name of the promotion associated with an event + EventParameterPromotionName EventParameter = "promotion_name" + // EventParameterAchievementId The ID of an achievement that was unlocked in a game + EventParameterAchievementId EventParameter = "achievement_id" + // EventParameterCharacter The name of a character in a game + EventParameterCharacter EventParameter = "character" + // EventParameterLevelName The name of the level in a game + EventParameterLevelName EventParameter = "level_name" + // EventParameterVirtualCurrencyName The name of a virtual currency + EventParameterVirtualCurrencyName EventParameter = "virtual_currency_name" + // EventParameterFileExtension The extension of a file download + EventParameterFileExtension EventParameter = "file_extension" + // EventParameterFileName The page path of a file download + EventParameterFileName EventParameter = "file_name" + // EventParameterFormDestination The URL to which a form is being submitted + EventParameterFormDestination EventParameter = "form_destination" + // EventParameterFormId The HTML id attribution of the