forked from jpillora/go-ogle-analytics
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ga): upgrade measurement protocol to GA4 from UA
Signed-off-by: Niladri Halder <niladri.halder26@gmail.com>
- Loading branch information
Showing
23 changed files
with
352 additions
and
7,661 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
example/tracker-id.txt | ||
example/tracker-id.txt | ||
**/.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"net" | ||
"net/http" | ||
"regexp" | ||
|
||
"github.com/openebs/lib-csi/pkg/common/errors" | ||
) | ||
|
||
var measurementIDMatcher = regexp.MustCompile(`^G-[a-zA-Z0-9]+$`) | ||
|
||
type MeasurementClientOption func(*MeasurementClient) error | ||
|
||
type MeasurementClient struct { | ||
HttpClient *http.Client | ||
apiSecret string | ||
measurementId string | ||
clientId string | ||
} | ||
|
||
func NewMeasurementClient(opts ...MeasurementClientOption) (*MeasurementClient, error) { | ||
dialer := &net.Dialer{ | ||
Resolver: &net.Resolver{ | ||
PreferGo: true, | ||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) { | ||
dialer := net.Dialer{} | ||
return dialer.DialContext(ctx, network, "8.8.8.8:53") | ||
}, | ||
}, | ||
} | ||
c := &MeasurementClient{ | ||
HttpClient: &http.Client{ | ||
Transport: &http.Transport{ | ||
DialContext: dialer.DialContext, | ||
}, | ||
}, | ||
} | ||
|
||
var err error | ||
for _, opt := range opts { | ||
err = opt(c) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed to build MeasurementClient") | ||
} | ||
} | ||
|
||
return c, nil | ||
} | ||
|
||
func WithApiSecret(secret string) MeasurementClientOption { | ||
return func(s *MeasurementClient) error { | ||
if len(secret) == 0 { | ||
return errors.Errorf("failed to set api_secret: secret is an empty string") | ||
} | ||
|
||
s.apiSecret = secret | ||
return nil | ||
} | ||
} | ||
|
||
func WithMeasurementId(measurementId string) MeasurementClientOption { | ||
return func(s *MeasurementClient) error { | ||
if len(measurementId) == 0 { | ||
return errors.Errorf("failed to set measurement_id: id is an empty string") | ||
} | ||
|
||
if !measurementIDMatcher.MatchString(measurementId) { | ||
return errors.Errorf("Invalid measurement_id: %s", measurementId) | ||
} | ||
|
||
s.measurementId = measurementId | ||
return nil | ||
} | ||
} | ||
|
||
func WithClientId(clientId string) MeasurementClientOption { | ||
return func(s *MeasurementClient) error { | ||
if len(clientId) == 0 { | ||
return errors.Errorf("failed to set client_id: id is an empty string") | ||
} | ||
|
||
s.clientId = clientId | ||
return nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package client | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"net/http" | ||
"net/url" | ||
|
||
"github.com/openebs/lib-csi/pkg/common/errors" | ||
|
||
"github.com/openebs/go-ogle-analytics/event" | ||
"github.com/openebs/go-ogle-analytics/payload" | ||
) | ||
|
||
func (c *MeasurementClient) Copy() *MeasurementClient { | ||
cpy := *c | ||
return &cpy | ||
} | ||
|
||
func (c *MeasurementClient) addFields(v url.Values) { | ||
v.Add("api_secret", c.apiSecret) | ||
v.Add("measurement_id", c.measurementId) | ||
} | ||
|
||
func (c *MeasurementClient) Send(event *event.OpenebsEvent) error { | ||
|
||
client := c.Copy() | ||
|
||
dataPayload, err := payload.NewPayload( | ||
payload.WithClientId(client.clientId), | ||
payload.WithOpenebsEvent(event), | ||
) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
jsonData, err := json.Marshal(dataPayload) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
gaUrl := "https://www.google-analytics.com/mp/collect" | ||
|
||
req, err := http.NewRequest("POST", gaUrl, bytes.NewReader(jsonData)) | ||
v := req.URL.Query() | ||
client.addFields(v) | ||
req.URL.RawQuery = v.Encode() | ||
|
||
req.Header.Set("Content-Type", "application/json") | ||
|
||
resp, err := client.HttpClient.Do(req) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if resp.StatusCode/100 != 2 { | ||
return errors.Errorf("Rejected by Google with code %d", resp.StatusCode) | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.