mirror of
https://github.com/foomo/sesamy-go.git
synced 2025-10-16 12:35:43 +00:00
feat: add parameters and restructure code
This commit is contained in:
parent
7100ab858b
commit
b45f2c844d
@ -79,25 +79,12 @@ func (p *Publisher) Publish(topic string, messages ...*message.Message) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
values, body, err := mpv2.Marshal(event)
|
values, body, err := mpv2.Encode(event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: `richsstsse` seems to be last parameter in the query to let's ensure it stays that way
|
req, err := http.NewRequestWithContext(msg.Context(), http.MethodPost, fmt.Sprintf("%s?%s", p.url, mpv2.EncodeValues(values)), body)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to create request")
|
return errors.Wrap(err, "failed to create request")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -138,7 +138,7 @@ func (s *Subscriber) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// unmarshal event
|
// unmarshal event
|
||||||
var event *mpv2.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"))
|
keelhttputils.InternalServerError(l, w, r, errors.Wrap(err, "failed to marshal url values"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"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 {
|
func (c *Client) SendRaw(r *http.Request, event *Event) error {
|
||||||
values, body, err := Marshal(event)
|
values, body, err := Encode(event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to marshall event")
|
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(
|
req, err := http.NewRequestWithContext(
|
||||||
r.Context(),
|
r.Context(),
|
||||||
http.MethodPost,
|
http.MethodPost,
|
||||||
c.url+"?"+values.Encode(),
|
fmt.Sprintf("%s?%s", c.url, EncodeValues(values)),
|
||||||
body,
|
body,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
13
measurementprotocol/v2/contants.go
Normal file
13
measurementprotocol/v2/contants.go
Normal file
@ -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"
|
||||||
|
)
|
||||||
3
measurementprotocol/v2/data.go
Normal file
3
measurementprotocol/v2/data.go
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package v2
|
||||||
|
|
||||||
|
type Data map[string]any
|
||||||
98
measurementprotocol/v2/decode.go
Normal file
98
measurementprotocol/v2/decode.go
Normal file
@ -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
|
||||||
|
}
|
||||||
@ -10,7 +10,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUnmarshalURLValues(t *testing.T) {
|
func TestDecode(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args string
|
args string
|
||||||
@ -32,48 +32,15 @@ func TestUnmarshalURLValues(t *testing.T) {
|
|||||||
u, err := url.ParseQuery(tt.args)
|
u, err := url.ParseQuery(tt.args)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
e := &mpv2.Event{}
|
e := &mpv2.Event{}
|
||||||
if err := mpv2.UnmarshalURLValues(u, e); !assert.ErrorIs(t, err, tt.want) {
|
if err := mpv2.Decode(u, e); !assert.ErrorIs(t, err, tt.want) {
|
||||||
t.Errorf("UnmarshalURLValues() = %v, want %v", err, tt.want)
|
t.Errorf("Decode() = %v, want %v", err, tt.want)
|
||||||
t.Log(e)
|
t.Log(e)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMarshalURLValues(t *testing.T) {
|
func TestDecodeMapValue(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) {
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args string
|
args string
|
||||||
@ -99,7 +66,7 @@ func TestCollect_decodeMapValue(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
for k, v := range values {
|
for k, v := range values {
|
||||||
if got, err := mpv2.DecodeMapValue(k, v, d); assert.NoError(t, err) && got != tt.want {
|
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)
|
t.Log(d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
102
measurementprotocol/v2/encode.go
Normal file
102
measurementprotocol/v2/encode.go
Normal file
@ -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, "~")
|
||||||
|
}
|
||||||
43
measurementprotocol/v2/encode_test.go
Normal file
43
measurementprotocol/v2/encode_test.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
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 {
|
type AddPaymentInfo struct {
|
||||||
Currency string
|
Currency string `json:"currency,omitempty"`
|
||||||
Value float64
|
Value float64 `json:"value,omitempty"`
|
||||||
Coupon string
|
Coupon string `json:"coupon,omitempty"`
|
||||||
PaymentType string
|
PaymentType string `json:"payment_type,omitempty"`
|
||||||
Items []*Item
|
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))
|
items := make([]*mpv2.Item, len(e.Items))
|
||||||
for i, item := range e.Items {
|
for i, item := range e.Items {
|
||||||
items[i] = item.MPv2()
|
items[i] = item.MarshalMPv2()
|
||||||
}
|
}
|
||||||
eventParameter := map[string]string{}
|
eventParameter := map[string]string{}
|
||||||
mp.AddStringMap(eventParameter, mpv2.EventParameterCoupon.String(), mp.SetString(e.Coupon))
|
mp.AddStringMap(eventParameter, mpv2.EventParameterCoupon.String(), mp.SetString(e.Coupon))
|
||||||
@ -63,5 +63,5 @@ func (e *AddPaymentInfo) MPv2() *mpv2.Event {
|
|||||||
EventParameter: mp.SetStringMap(eventParameter),
|
EventParameter: mp.SetStringMap(eventParameter),
|
||||||
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
||||||
Items: items,
|
Items: items,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
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 {
|
type AddShippingInfo struct {
|
||||||
Currency string
|
Currency string `json:"currency,omitempty"`
|
||||||
Value float64
|
Value float64 `json:"value,omitempty"`
|
||||||
Coupon string
|
Coupon string `json:"coupon,omitempty"`
|
||||||
ShippingTier string
|
ShippingTier string `json:"shipping_tier,omitempty"`
|
||||||
Items []*Item
|
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))
|
items := make([]*mpv2.Item, len(e.Items))
|
||||||
for i, item := range e.Items {
|
for i, item := range e.Items {
|
||||||
items[i] = item.MPv2()
|
items[i] = item.MarshalMPv2()
|
||||||
}
|
}
|
||||||
eventParameter := map[string]string{}
|
eventParameter := map[string]string{}
|
||||||
mp.AddStringMap(eventParameter, mpv2.EventParameterCoupon.String(), mp.SetString(e.Coupon))
|
mp.AddStringMap(eventParameter, mpv2.EventParameterCoupon.String(), mp.SetString(e.Coupon))
|
||||||
@ -63,5 +63,5 @@ func (e *AddShippingInfo) MPv2() *mpv2.Event {
|
|||||||
EventParameter: mp.SetStringMap(eventParameter),
|
EventParameter: mp.SetStringMap(eventParameter),
|
||||||
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
||||||
Items: items,
|
Items: items,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
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 {
|
type AddToCart struct {
|
||||||
Currency string
|
Currency string `json:"currency,omitempty"`
|
||||||
Value float64
|
Value float64 `json:"value,omitempty"`
|
||||||
Items []*Item
|
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))
|
items := make([]*mpv2.Item, len(e.Items))
|
||||||
for i, item := range e.Items {
|
for i, item := range e.Items {
|
||||||
items[i] = item.MPv2()
|
items[i] = item.MarshalMPv2()
|
||||||
}
|
}
|
||||||
eventParameterNumber := map[string]string{}
|
eventParameterNumber := map[string]string{}
|
||||||
mp.AddStringMap(eventParameterNumber, mpv2.EventParameterNumberValue.String(), mp.SetFloat64(e.Value))
|
mp.AddStringMap(eventParameterNumber, mpv2.EventParameterNumberValue.String(), mp.SetFloat64(e.Value))
|
||||||
@ -56,5 +56,5 @@ func (e *AddToCart) MPv2() *mpv2.Event {
|
|||||||
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
||||||
Items: items,
|
Items: items,
|
||||||
Richsstsse: mp.Set(""),
|
Richsstsse: mp.Set(""),
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
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 {
|
type AddToWishlist struct {
|
||||||
Currency string
|
Currency string `json:"currency,omitempty"`
|
||||||
Value float64
|
Value float64 `json:"value,omitempty"`
|
||||||
Items []*Item
|
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))
|
items := make([]*mpv2.Item, len(e.Items))
|
||||||
for i, item := range e.Items {
|
for i, item := range e.Items {
|
||||||
items[i] = item.MPv2()
|
items[i] = item.MarshalMPv2()
|
||||||
}
|
}
|
||||||
eventParameterNumber := map[string]string{}
|
eventParameterNumber := map[string]string{}
|
||||||
mp.AddStringMap(eventParameterNumber, mpv2.EventParameterNumberValue.String(), mp.SetFloat64(e.Value))
|
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),
|
Currency: mp.SetString(e.Currency),
|
||||||
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
||||||
Items: items,
|
Items: items,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
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 {
|
type BeginCheckout struct {
|
||||||
Currency string
|
Currency string `json:"currency,omitempty"`
|
||||||
Value float64
|
Value float64 `json:"value,omitempty"`
|
||||||
Coupon string
|
Coupon string `json:"coupon,omitempty"`
|
||||||
Items []*Item
|
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))
|
items := make([]*mpv2.Item, len(e.Items))
|
||||||
for i, item := range e.Items {
|
for i, item := range e.Items {
|
||||||
items[i] = item.MPv2()
|
items[i] = item.MarshalMPv2()
|
||||||
}
|
}
|
||||||
eventParameter := map[string]string{}
|
eventParameter := map[string]string{}
|
||||||
mp.AddStringMap(eventParameter, mpv2.EventParameterCoupon.String(), mp.SetString(e.Coupon))
|
mp.AddStringMap(eventParameter, mpv2.EventParameterCoupon.String(), mp.SetString(e.Coupon))
|
||||||
@ -60,5 +60,5 @@ func (e *BeginCheckout) MPv2() *mpv2.Event {
|
|||||||
EventParameter: mp.SetStringMap(eventParameter),
|
EventParameter: mp.SetStringMap(eventParameter),
|
||||||
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
||||||
Items: items,
|
Items: items,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,43 +6,43 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
ID string
|
Affiliation string `json:"affiliation,omitempty"`
|
||||||
Name string
|
Coupon string `json:"coupon,omitempty"`
|
||||||
Brand string
|
Discount float64 `json:"discount,omitempty"`
|
||||||
CategoryHierarchy1 string
|
Index int `json:"index,omitempty"`
|
||||||
CategoryHierarchy2 string
|
ItemBrand string `json:"item_brand,omitempty"`
|
||||||
CategoryHierarchy3 string
|
ItemCategory string `json:"item_category,omitempty"`
|
||||||
CategoryHierarchy4 string
|
ItemCategory2 string `json:"item_category2,omitempty"`
|
||||||
CategoryHierarchy5 string
|
ItemCategory3 string `json:"item_category3,omitempty"`
|
||||||
Price string
|
ItemCategory4 string `json:"item_category4,omitempty"`
|
||||||
Quantity float64
|
ItemCategory5 string `json:"item_category5,omitempty"`
|
||||||
Variant string
|
ItemID string `json:"item_id,omitempty"`
|
||||||
Coupon string
|
ItemListName string `json:"item_list_name,omitempty"`
|
||||||
Discount float64
|
ItemName string `json:"item_name,omitempty"`
|
||||||
Index int
|
ItemVariant string `json:"item_variant,omitempty"`
|
||||||
ListName string
|
ItemListID string `json:"listId,omitempty"`
|
||||||
ListID string
|
LocationID string `json:"location_id,omitempty"`
|
||||||
Affiliation string
|
Price string `json:"price,omitempty"`
|
||||||
LocationID string
|
Quantity float64 `json:"quantity,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Item) MPv2() *mpv2.Item {
|
func (e *Item) MarshalMPv2() *mpv2.Item {
|
||||||
return &mpv2.Item{
|
return &mpv2.Item{
|
||||||
ID: mp.SetString(e.ID),
|
ID: mp.SetString(e.ItemID),
|
||||||
Name: mp.SetString(e.Name),
|
Name: mp.SetString(e.ItemName),
|
||||||
Brand: mp.SetString(e.Brand),
|
Brand: mp.SetString(e.ItemBrand),
|
||||||
CategoryHierarchy1: mp.SetString(e.CategoryHierarchy1),
|
CategoryHierarchy1: mp.SetString(e.ItemCategory),
|
||||||
CategoryHierarchy2: mp.SetString(e.CategoryHierarchy2),
|
CategoryHierarchy2: mp.SetString(e.ItemCategory2),
|
||||||
CategoryHierarchy3: mp.SetString(e.CategoryHierarchy3),
|
CategoryHierarchy3: mp.SetString(e.ItemCategory3),
|
||||||
CategoryHierarchy4: mp.SetString(e.CategoryHierarchy4),
|
CategoryHierarchy4: mp.SetString(e.ItemCategory4),
|
||||||
CategoryHierarchy5: mp.SetString(e.CategoryHierarchy5),
|
CategoryHierarchy5: mp.SetString(e.ItemCategory5),
|
||||||
Price: mp.SetString(e.Price),
|
Price: mp.SetString(e.Price),
|
||||||
Quantity: mp.SetFloat64(e.Quantity),
|
Quantity: mp.SetFloat64(e.Quantity),
|
||||||
Variant: mp.SetString(e.Variant),
|
Variant: mp.SetString(e.ItemVariant),
|
||||||
Coupon: mp.SetString(e.Coupon),
|
Coupon: mp.SetString(e.Coupon),
|
||||||
Discount: mp.SetFloat64(e.Discount),
|
Discount: mp.SetFloat64(e.Discount),
|
||||||
ListName: mp.SetString(e.ListName),
|
ListName: mp.SetString(e.ItemListName),
|
||||||
ListID: mp.SetString(e.ListID),
|
ListID: mp.SetString(e.ItemListID),
|
||||||
ListPosition: mp.SetInt(e.Index),
|
ListPosition: mp.SetInt(e.Index),
|
||||||
Affiliation: mp.SetString(e.Affiliation),
|
Affiliation: mp.SetString(e.Affiliation),
|
||||||
LocationID: mp.SetString(e.LocationID),
|
LocationID: mp.SetString(e.LocationID),
|
||||||
|
|||||||
@ -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
|
Reference: https://developers.google.com/tag-platform/gtagjs/reference/events#login
|
||||||
*/
|
*/
|
||||||
type Login struct {
|
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{}
|
eventParameter := map[string]string{}
|
||||||
mp.AddStringMap(eventParameter, mpv2.EventParameterMethod.String(), mp.SetString(e.Method))
|
mp.AddStringMap(eventParameter, mpv2.EventParameterMethod.String(), mp.SetString(e.Method))
|
||||||
return &mpv2.Event{
|
return &mpv2.Event{
|
||||||
EventName: mp.Set(mpv2.EventNameLogin),
|
EventName: mp.Set(mpv2.EventNameLogin),
|
||||||
EventParameter: mp.SetStringMap(eventParameter),
|
EventParameter: mp.SetStringMap(eventParameter),
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
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 {
|
type Purchase struct {
|
||||||
Currency string
|
Currency string `json:"currency,omitempty"`
|
||||||
Value float64
|
Value float64 `json:"value,omitempty"`
|
||||||
TransactionID string
|
TransactionID string `json:"transaction_id,omitempty"`
|
||||||
Coupon string
|
Coupon string `json:"coupon,omitempty"`
|
||||||
Shipping float64
|
Shipping float64 `json:"shipping,omitempty"`
|
||||||
Tax float64
|
Tax float64 `json:"tax,omitempty"`
|
||||||
Items []*Item
|
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))
|
items := make([]*mpv2.Item, len(e.Items))
|
||||||
for i, item := range e.Items {
|
for i, item := range e.Items {
|
||||||
items[i] = item.MPv2()
|
items[i] = item.MarshalMPv2()
|
||||||
}
|
}
|
||||||
eventParameter := map[string]string{}
|
eventParameter := map[string]string{}
|
||||||
mp.AddStringMap(eventParameter, mpv2.EventParameterTransactionID.String(), mp.SetString(e.TransactionID))
|
mp.AddStringMap(eventParameter, mpv2.EventParameterTransactionID.String(), mp.SetString(e.TransactionID))
|
||||||
@ -69,5 +69,5 @@ func (e *Purchase) MPv2() *mpv2.Event {
|
|||||||
EventParameter: mp.SetStringMap(eventParameter),
|
EventParameter: mp.SetStringMap(eventParameter),
|
||||||
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
||||||
Items: items,
|
Items: items,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
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 {
|
type Refund struct {
|
||||||
Currency string
|
Currency string `json:"currency,omitempty"`
|
||||||
Value float64
|
Value float64 `json:"value,omitempty"`
|
||||||
TransactionID string
|
TransactionID string `json:"transaction_id,omitempty"`
|
||||||
Coupon string
|
Coupon string `json:"coupon,omitempty"`
|
||||||
Shipping float64
|
Shipping float64 `json:"shipping,omitempty"`
|
||||||
Tax float64
|
Tax float64 `json:"tax,omitempty"`
|
||||||
Items []*Item
|
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))
|
items := make([]*mpv2.Item, len(e.Items))
|
||||||
for i, item := range e.Items {
|
for i, item := range e.Items {
|
||||||
items[i] = item.MPv2()
|
items[i] = item.MarshalMPv2()
|
||||||
}
|
}
|
||||||
eventParameter := map[string]string{}
|
eventParameter := map[string]string{}
|
||||||
mp.AddStringMap(eventParameter, mpv2.EventParameterTransactionID.String(), mp.SetString(e.TransactionID))
|
mp.AddStringMap(eventParameter, mpv2.EventParameterTransactionID.String(), mp.SetString(e.TransactionID))
|
||||||
@ -69,5 +69,5 @@ func (e *Refund) MPv2() *mpv2.Event {
|
|||||||
EventParameter: mp.SetStringMap(eventParameter),
|
EventParameter: mp.SetStringMap(eventParameter),
|
||||||
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
||||||
Items: items,
|
Items: items,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
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 {
|
type RemoveFromCart struct {
|
||||||
Currency string
|
Currency string `json:"currency,omitempty"`
|
||||||
Value float64
|
Value float64 `json:"value,omitempty"`
|
||||||
Items []*Item
|
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))
|
items := make([]*mpv2.Item, len(e.Items))
|
||||||
for i, item := range e.Items {
|
for i, item := range e.Items {
|
||||||
items[i] = item.MPv2()
|
items[i] = item.MarshalMPv2()
|
||||||
}
|
}
|
||||||
eventParameterNumber := map[string]string{}
|
eventParameterNumber := map[string]string{}
|
||||||
mp.AddStringMap(eventParameterNumber, mpv2.EventParameterNumberValue.String(), mp.SetFloat64(e.Value))
|
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),
|
Currency: mp.SetString(e.Currency),
|
||||||
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
EventParameterNumber: mp.SetStringMap(eventParameterNumber),
|
||||||
Items: items,
|
Items: items,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
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 {
|
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{}
|
eventParameter := map[string]string{}
|
||||||
mp.AddStringMap(eventParameter, mpv2.EventParameterSearchTerm.String(), mp.SetString(e.SearchTerm))
|
mp.AddStringMap(eventParameter, mpv2.EventParameterSearchTerm.String(), mp.SetString(e.SearchTerm))
|
||||||
return &mpv2.Event{
|
return &mpv2.Event{
|
||||||
EventName: mp.Set(mpv2.EventNameSearch),
|
EventName: mp.Set(mpv2.EventNameSearch),
|
||||||
EventParameter: mp.SetStringMap(eventParameter),
|
EventParameter: mp.SetStringMap(eventParameter),
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
Reference: https://developers.google.com/tag-platform/gtagjs/reference/events#sign_up
|
||||||
*/
|
*/
|
||||||
type SignUp struct {
|
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{}
|
eventParameter := map[string]string{}
|
||||||
mp.AddStringMap(eventParameter, mpv2.EventParameterMethod.String(), mp.SetString(e.Method))
|
mp.AddStringMap(eventParameter, mpv2.EventParameterMethod.String(), mp.SetString(e.Method))
|
||||||
return &mpv2.Event{
|
return &mpv2.Event{
|
||||||
EventName: mp.Set(mpv2.EventNameSignUp),
|
EventName: mp.Set(mpv2.EventNameSignUp),
|
||||||
EventParameter: mp.SetStringMap(eventParameter),
|
EventParameter: mp.SetStringMap(eventParameter),
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,162 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
|
// EventParameter as string
|
||||||
|
// See https://support.google.com/analytics/table/13594742?sjid=7861230991468479976-EU
|
||||||
type EventParameter string
|
type EventParameter string
|
||||||
|
|
||||||
const (
|
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 <form> DOM element
|
||||||
|
EventParameterFormId EventParameter = "form_id"
|
||||||
|
// EventParameterFormName The HTML name attribute of the <form> DOM element
|
||||||
|
EventParameterFormName EventParameter = "form_name"
|
||||||
|
// EventParameterFormSubmitText The text of the submit button, if present
|
||||||
|
EventParameterFormSubmitText EventParameter = "form_submit_text"
|
||||||
|
// EventParameterGroupId The ID of a group
|
||||||
|
EventParameterGroupId EventParameter = "group_id"
|
||||||
|
// EventParameterLanguage The language setting of a user’s browser or device, displayed as the ISO 639 language code
|
||||||
|
EventParameterLanguage EventParameter = "language"
|
||||||
|
// EventParameterPercentScrolled The percentage down the page that the user scrolled
|
||||||
|
EventParameterPercentScrolled EventParameter = "percent_scrolled"
|
||||||
|
// EventParameterSearchTerm The strings or keywords used in a search
|
||||||
|
EventParameterSearchTerm EventParameter = "search_term"
|
||||||
|
// EventParameterLinkClasses The HTML class attribute for an outbound link or file download
|
||||||
|
EventParameterLinkClasses EventParameter = "link_classes"
|
||||||
|
// EventParameterLinkDomain The destination domain of an outbound link or file download
|
||||||
|
EventParameterLinkDomain EventParameter = "link_domain"
|
||||||
|
// EventParameterLinkId The ID for an outbound link or file download
|
||||||
|
EventParameterLinkId EventParameter = "link_id"
|
||||||
|
// EventParameterLinkUrl The full URL for an outbound link or file download
|
||||||
|
EventParameterLinkUrl EventParameter = "link_url"
|
||||||
|
// EventParameterOutbound Indicates whether a click was on an outbound link
|
||||||
|
EventParameterOutbound EventParameter = "outbound"
|
||||||
|
// EventParameterContentGroup The content group associated with a page or screen
|
||||||
|
EventParameterContentGroup EventParameter = "content_group"
|
||||||
|
// EventParameterContentId An ID for an article of content that a user interacted with
|
||||||
|
EventParameterContentId EventParameter = "content_id"
|
||||||
|
// EventParameterContentType The type of content that a user interacted with
|
||||||
|
EventParameterContentType EventParameter = "content_type"
|
||||||
|
// EventParameterPageLocation The complete URL of the webpage that someone visited on your website
|
||||||
|
EventParameterPageLocation EventParameter = "page_location"
|
||||||
|
// EventParameterPageReferrer The referring URL, which is the user's previous URL and can be your website's domain or other domains
|
||||||
|
EventParameterPageReferrer EventParameter = "page_referrer"
|
||||||
|
// EventParameterPageTitle The HTML page title that you set on your website
|
||||||
|
EventParameterPageTitle EventParameter = "page_title"
|
||||||
|
// EventParameterScreenResolution The resolution of a device, in the format (Width)x(Height)
|
||||||
|
EventParameterScreenResolution EventParameter = "screen_resolution"
|
||||||
|
// EventParameterAdFormat The format of an advertisement in an app
|
||||||
|
EventParameterAdFormat EventParameter = "ad_format"
|
||||||
|
// EventParameterAdPlatform The platform used to surface an advertisement in an app
|
||||||
|
EventParameterAdPlatform EventParameter = "ad_platform"
|
||||||
|
// EventParameterAdSource The source network that served an advertisement
|
||||||
|
EventParameterAdSource EventParameter = "ad_source"
|
||||||
|
// EventParameterAdUnitId The unique identifier for an ad unit
|
||||||
|
EventParameterAdUnitId EventParameter = "ad_unit_id"
|
||||||
|
// EventParameterAdUnitName The name you choose for an ad unit
|
||||||
|
EventParameterAdUnitName EventParameter = "ad_unit_name"
|
||||||
|
// EventParameterVideoProvider The source of an embedded video
|
||||||
|
EventParameterVideoProvider EventParameter = "video_provider"
|
||||||
|
// EventParameterVideoTitle The title of an embedded video
|
||||||
|
EventParameterVideoTitle EventParameter = "video_title"
|
||||||
|
// EventParameterVideoUrl The url of an embedded video
|
||||||
|
EventParameterVideoUrl EventParameter = "video_url"
|
||||||
|
|
||||||
|
// Additional undocumented parameters
|
||||||
|
|
||||||
EventParameterMethod EventParameter = "method"
|
EventParameterMethod EventParameter = "method"
|
||||||
EventParameterCoupon EventParameter = "coupon"
|
|
||||||
EventParameterPaymentType EventParameter = "payment_type"
|
EventParameterPaymentType EventParameter = "payment_type"
|
||||||
EventParameterShippingTier EventParameter = "shipping_tier"
|
|
||||||
EventParameterTransactionID EventParameter = "transaction_id"
|
EventParameterTransactionID EventParameter = "transaction_id"
|
||||||
EventParameterSearchTerm EventParameter = "search_term"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s EventParameter) String() string {
|
func (s EventParameter) String() string {
|
||||||
|
|||||||
@ -1,11 +1,23 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
|
// EventParameterNumber as number
|
||||||
|
// See https://support.google.com/analytics/table/13594742?sjid=7861230991468479976-EU
|
||||||
type EventParameterNumber string
|
type EventParameterNumber string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
EventParameterNumberValue EventParameterNumber = "value"
|
EventParameterNumberValue EventParameterNumber = "value"
|
||||||
|
// EventParameterNumberFirebaseError The error code reported by the Firebase SDK.
|
||||||
|
EventParameterNumberFirebaseError EventParameterNumber = "firebase_error"
|
||||||
|
// EventParameterNumberFreeTrial Signifies that an in-app purchase is a free trial
|
||||||
|
EventParameterNumberFreeTrial EventParameterNumber = "free_trial"
|
||||||
|
// EventParameterNumberMessageDeviceTime The Firebase Cloud Messaging or Firebase In-App Messaging delivery epoch timestamp in UTC. (None)
|
||||||
|
EventParameterNumberMessageDeviceTime EventParameterNumber = "message_device_time"
|
||||||
|
// EventParameterNumberMessageTime The Firebase Cloud Messaging message notification epoch timestamp in UTC. (None)
|
||||||
|
EventParameterNumberMessageTime EventParameterNumber = "message_time"
|
||||||
|
// EventParameterNumberShipping The shipping cost associated with a transaction
|
||||||
EventParameterNumberShipping EventParameterNumber = "shipping"
|
EventParameterNumberShipping EventParameterNumber = "shipping"
|
||||||
EventParameterNumberTax EventParameterNumber = "tax"
|
// EventParameterNumberTax The tax cost associated with a transaction
|
||||||
|
EventParameterNumberTax EventParameterNumber = "tax"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s EventParameterNumber) String() string {
|
func (s EventParameterNumber) String() string {
|
||||||
|
|||||||
5
measurementprotocol/v2/marshaler.go
Normal file
5
measurementprotocol/v2/marshaler.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package v2
|
||||||
|
|
||||||
|
type Marshler interface {
|
||||||
|
MarshalMPv2() (*Event, error)
|
||||||
|
}
|
||||||
@ -1,202 +0,0 @@
|
|||||||
package v2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/url"
|
|
||||||
"regexp"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
RegexProduct = regexp.MustCompile(`pr([1-9]|[1-9][0-9]|1[0-9]{2}|200)`)
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
ParameterItem = "pr"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Data map[string]any
|
|
||||||
|
|
||||||
func Marshal(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
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnmarshalURLValues(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
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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, "~")
|
|
||||||
}
|
|
||||||
5
measurementprotocol/v2/unmarshaler.go
Normal file
5
measurementprotocol/v2/unmarshaler.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package v2
|
||||||
|
|
||||||
|
type Unmarshler interface {
|
||||||
|
UnmarshalMPv2(*Event) error
|
||||||
|
}
|
||||||
22
measurementprotocol/v2/values.go
Normal file
22
measurementprotocol/v2/values.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package v2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EncodeValues
|
||||||
|
// NOTE: `richsstsse` seems to be last parameter in the query to let's ensure it stays that way
|
||||||
|
func EncodeValues(values url.Values) string {
|
||||||
|
var richsstsse bool
|
||||||
|
if values.Has("richsstsse") {
|
||||||
|
values.Del("richsstsse")
|
||||||
|
richsstsse = true
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := values.Encode()
|
||||||
|
|
||||||
|
if richsstsse {
|
||||||
|
ret += "&richsstsse"
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user