diff --git a/.changelog/1474.txt b/.changelog/1474.txt
new file mode 100644
index 00000000000..6c275e3ec45
--- /dev/null
+++ b/.changelog/1474.txt
@@ -0,0 +1,3 @@
+```release-note:enhancement
+zaraz: Add support for CRUD APIs
+```
diff --git a/zaraz.go b/zaraz.go
new file mode 100644
index 00000000000..dedfdc4c977
--- /dev/null
+++ b/zaraz.go
@@ -0,0 +1,421 @@
+package cloudflare
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "time"
+
+ "github.com/goccy/go-json"
+)
+
+type ZarazConfig struct {
+ DebugKey string `json:"debugKey"`
+ Tools map[string]ZarazTool `json:"tools"`
+ Triggers map[string]ZarazTrigger `json:"triggers"`
+ ZarazVersion int64 `json:"zarazVersion"`
+ Consent ZarazConsent `json:"consent,omitempty"`
+ DataLayer *bool `json:"dataLayer,omitempty"`
+ Dlp []any `json:"dlp,omitempty"`
+ HistoryChange *bool `json:"historyChange,omitempty"`
+ Settings ZarazConfigSettings `json:"settings,omitempty"`
+ Variables map[string]ZarazVariable `json:"variables,omitempty"`
+}
+
+type ZarazWorker struct {
+ EscapedWorkerName string `json:"escapedWorkerName"`
+ WorkerTag string `json:"workerTag"`
+ MutableId string `json:"mutableId,omitempty"`
+}
+type ZarazConfigSettings struct {
+ AutoInjectScript *bool `json:"autoInjectScript"`
+ InjectIframes *bool `json:"injectIframes,omitempty"`
+ Ecommerce *bool `json:"ecommerce,omitempty"`
+ HideQueryParams *bool `json:"hideQueryParams,omitempty"`
+ HideIpAddress *bool `json:"hideIPAddress,omitempty"`
+ HideUserAgent *bool `json:"hideUserAgent,omitempty"`
+ HideExternalReferer *bool `json:"hideExternalReferer,omitempty"`
+ CookieDomain string `json:"cookieDomain,omitempty"`
+ InitPath string `json:"initPath,omitempty"`
+ ScriptPath string `json:"scriptPath,omitempty"`
+ TrackPath string `json:"trackPath,omitempty"`
+ EventsApiPath string `json:"eventsApiPath,omitempty"`
+ McRootPath string `json:"mcRootPath,omitempty"`
+ ContextEnricher ZarazWorker `json:"contextEnricher,omitempty"`
+}
+
+type ZarazNeoEvent struct {
+ BlockingTriggers []string `json:"blockingTriggers"`
+ FiringTriggers []string `json:"firingTriggers"`
+ Data map[string]any `json:"data"`
+ ActionType string `json:"actionType,omitempty"`
+}
+
+type ZarazToolType string
+
+const (
+ ZarazToolLibrary ZarazToolType = "library"
+ ZarazToolComponent ZarazToolType = "component"
+ ZarazToolCustomMc ZarazToolType = "custom-mc"
+)
+
+type ZarazTool struct {
+ BlockingTriggers []string `json:"blockingTriggers"`
+ Enabled *bool `json:"enabled"`
+ DefaultFields map[string]any `json:"defaultFields"`
+ Name string `json:"name"`
+ NeoEvents []ZarazNeoEvent `json:"neoEvents"`
+ Type ZarazToolType `json:"type"`
+ DefaultPurpose string `json:"defaultPurpose,omitempty"`
+ Library string `json:"library,omitempty"`
+ Component string `json:"component,omitempty"`
+ Permissions []string `json:"permissions,omitempty"`
+ Settings map[string]any `json:"settings,omitempty"`
+ Worker ZarazWorker `json:"worker,omitempty"`
+}
+
+type ZarazTriggerSystem string
+
+const ZarazPageload ZarazTriggerSystem = "pageload"
+
+type ZarazLoadRuleOp string
+
+type ZarazRuleType string
+
+const (
+ ZarazClickListener ZarazRuleType = "clickListener"
+ ZarazTimer ZarazRuleType = "timer"
+ ZarazFormSubmission ZarazRuleType = "formSubmission"
+ ZarazVariableMatch ZarazRuleType = "variableMatch"
+ ZarazScrollDepth ZarazRuleType = "scrollDepth"
+ ZarazElementVisibility ZarazRuleType = "elementVisibility"
+ ZarazClientEval ZarazRuleType = "clientEval"
+)
+
+type ZarazSelectorType string
+
+const (
+ ZarazXPath ZarazSelectorType = "xpath"
+ ZarazCSS ZarazSelectorType = "css"
+)
+
+type ZarazRuleSettings struct {
+ Type ZarazSelectorType `json:"type,omitempty"`
+ Selector string `json:"selector,omitempty"`
+ WaitForTags int `json:"waitForTags,omitempty"`
+ Interval int `json:"interval,omitempty"`
+ Limit int `json:"limit,omitempty"`
+ Validate *bool `json:"validate,omitempty"`
+ Variable string `json:"variable,omitempty"`
+ Match string `json:"match,omitempty"`
+ Positions string `json:"positions,omitempty"`
+ Op ZarazLoadRuleOp `json:"op,omitempty"`
+ Value string `json:"value,omitempty"`
+}
+
+type ZarazTriggerRule struct {
+ Id string `json:"id"`
+ Match string `json:"match,omitempty"`
+ Op ZarazLoadRuleOp `json:"op,omitempty"`
+ Value string `json:"value,omitempty"`
+ Action ZarazRuleType `json:"action"`
+ Settings ZarazRuleSettings `json:"settings"`
+}
+
+type ZarazTrigger struct {
+ Name string `json:"name"`
+ Description string `json:"description,omitempty"`
+ LoadRules []ZarazTriggerRule `json:"loadRules"`
+ ExcludeRules []ZarazTriggerRule `json:"excludeRules"`
+ ClientRules []any `json:"clientRules,omitempty"` // what is this?
+ System ZarazTriggerSystem `json:"system,omitempty"`
+}
+
+type ZarazVariableType string
+
+const (
+ ZarazVarString ZarazVariableType = "string"
+ ZarazVarSecret ZarazVariableType = "secret"
+ ZarazVarWorker ZarazVariableType = "worker"
+)
+
+type ZarazVariable struct {
+ Name string `json:"name"`
+ Type ZarazVariableType `json:"type"`
+ Value interface{} `json:"value"`
+}
+
+type ZarazButtonTextTranslations struct {
+ AcceptAll map[string]string `json:"accept_all"`
+ RejectAll map[string]string `json:"reject_all"`
+ ConfirmMyChoices map[string]string `json:"confirm_my_choices"`
+}
+
+type ZarazPurpose struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+}
+
+type ZarazPurposeWithTranslations struct {
+ Name map[string]string `json:"name"`
+ Description map[string]string `json:"description"`
+ Order int `json:"order"`
+}
+
+type ZarazConsent struct {
+ Enabled *bool `json:"enabled"`
+ ButtonTextTranslations ZarazButtonTextTranslations `json:"buttonTextTranslations,omitempty"`
+ CompanyEmail string `json:"companyEmail,omitempty"`
+ CompanyName string `json:"companyName,omitempty"`
+ CompanyStreetAddress string `json:"companyStreetAddress,omitempty"`
+ ConsentModalIntroHTML string `json:"consentModalIntroHTML,omitempty"`
+ ConsentModalIntroHTMLWithTranslations map[string]string `json:"consentModalIntroHTMLWithTranslations,omitempty"`
+ CookieName string `json:"cookieName,omitempty"`
+ CustomCSS string `json:"customCSS,omitempty"`
+ CustomIntroDisclaimerDismissed *bool `json:"customIntroDisclaimerDismissed,omitempty"`
+ DefaultLanguage string `json:"defaultLanguage,omitempty"`
+ HideModal *bool `json:"hideModal,omitempty"`
+ Purposes map[string]ZarazPurpose `json:"purposes,omitempty"`
+ PurposesWithTranslations map[string]ZarazPurposeWithTranslations `json:"purposesWithTranslations,omitempty"`
+}
+
+type ZarazConfigResponse struct {
+ Result ZarazConfig `json:"result"`
+ Response
+}
+
+type ZarazWorkflowResponse struct {
+ Result string `json:"result"`
+ Response
+}
+
+type ZarazPublishResponse struct {
+ Result string `json:"result"`
+ Response
+}
+
+type UpdateZarazConfigParams struct {
+ DebugKey string `json:"debugKey"`
+ Tools map[string]ZarazTool `json:"tools"`
+ Triggers map[string]ZarazTrigger `json:"triggers"`
+ ZarazVersion int64 `json:"zarazVersion"`
+ Consent ZarazConsent `json:"consent,omitempty"`
+ DataLayer *bool `json:"dataLayer,omitempty"`
+ Dlp []any `json:"dlp,omitempty"`
+ HistoryChange *bool `json:"historyChange,omitempty"`
+ Settings ZarazConfigSettings `json:"settings,omitempty"`
+ Variables map[string]ZarazVariable `json:"variables,omitempty"`
+}
+
+type UpdateZarazWorkflowParams struct {
+ Workflow string `json:"workflow"`
+}
+
+type PublishZarazConfigParams struct {
+ Description string `json:"description"`
+}
+
+type ZarazHistoryRecord struct {
+ ID int64 `json:"id,omitempty"`
+ UserID string `json:"userId,omitempty"`
+ Description string `json:"description,omitempty"`
+ CreatedAt *time.Time `json:"createdAt,omitempty"`
+ UpdatedAt *time.Time `json:"updatedAt,omitempty"`
+}
+
+type ZarazConfigHistoryListResponse struct {
+ Result []ZarazHistoryRecord `json:"result"`
+ Response
+ ResultInfo `json:"result_info"`
+}
+
+type ListZarazConfigHistoryParams struct {
+ ResultInfo
+}
+
+type GetZarazConfigsByIdResponse = map[string]interface{}
+
+// listZarazConfigHistoryDefaultPageSize represents the default per_page size of the API.
+var listZarazConfigHistoryDefaultPageSize int = 100
+
+func (api *API) GetZarazConfig(ctx context.Context, rc *ResourceContainer) (ZarazConfigResponse, error) {
+ if rc.Identifier == "" {
+ return ZarazConfigResponse{}, ErrMissingZoneID
+ }
+
+ uri := fmt.Sprintf("/zones/%s/settings/zaraz/v2/config", rc.Identifier)
+ res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+ if err != nil {
+ return ZarazConfigResponse{}, err
+ }
+
+ var recordResp ZarazConfigResponse
+ err = json.Unmarshal(res, &recordResp)
+ if err != nil {
+ return ZarazConfigResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+ }
+
+ return recordResp, nil
+}
+
+func (api *API) UpdateZarazConfig(ctx context.Context, rc *ResourceContainer, params UpdateZarazConfigParams) (ZarazConfigResponse, error) {
+ if rc.Identifier == "" {
+ return ZarazConfigResponse{}, ErrMissingZoneID
+ }
+
+ uri := fmt.Sprintf("/zones/%s/settings/zaraz/v2/config", rc.Identifier)
+ res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
+ if err != nil {
+ return ZarazConfigResponse{}, err
+ }
+
+ var updateResp ZarazConfigResponse
+ err = json.Unmarshal(res, &updateResp)
+ if err != nil {
+ return ZarazConfigResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+ }
+
+ return updateResp, nil
+}
+
+func (api *API) GetZarazWorkflow(ctx context.Context, rc *ResourceContainer) (ZarazWorkflowResponse, error) {
+ if rc.Identifier == "" {
+ return ZarazWorkflowResponse{}, ErrMissingZoneID
+ }
+
+ uri := fmt.Sprintf("/zones/%s/settings/zaraz/v2/workflow", rc.Identifier)
+ res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+ if err != nil {
+ return ZarazWorkflowResponse{}, err
+ }
+
+ var response ZarazWorkflowResponse
+ err = json.Unmarshal(res, &response)
+ if err != nil {
+ return ZarazWorkflowResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+ }
+
+ return response, nil
+}
+
+func (api *API) UpdateZarazWorkflow(ctx context.Context, rc *ResourceContainer, params UpdateZarazWorkflowParams) (ZarazWorkflowResponse, error) {
+ if rc.Identifier == "" {
+ return ZarazWorkflowResponse{}, ErrMissingZoneID
+ }
+
+ uri := fmt.Sprintf("/zones/%s/settings/zaraz/v2/workflow", rc.Identifier)
+ res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params.Workflow)
+ if err != nil {
+ return ZarazWorkflowResponse{}, err
+ }
+
+ var response ZarazWorkflowResponse
+ err = json.Unmarshal(res, &response)
+ if err != nil {
+ return ZarazWorkflowResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+ }
+
+ return response, nil
+}
+
+func (api *API) PublishZarazConfig(ctx context.Context, rc *ResourceContainer, params PublishZarazConfigParams) (ZarazPublishResponse, error) {
+ if rc.Identifier == "" {
+ return ZarazPublishResponse{}, ErrMissingZoneID
+ }
+
+ uri := fmt.Sprintf("/zones/%s/settings/zaraz/v2/publish", rc.Identifier)
+ res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params.Description)
+ if err != nil {
+ return ZarazPublishResponse{}, err
+ }
+
+ var response ZarazPublishResponse
+ err = json.Unmarshal(res, &response)
+ if err != nil {
+ return ZarazPublishResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+ }
+
+ return response, nil
+}
+
+func (api *API) ListZarazConfigHistory(ctx context.Context, rc *ResourceContainer, params ListZarazConfigHistoryParams) ([]ZarazHistoryRecord, *ResultInfo, error) {
+ if rc.Identifier == "" {
+ return nil, nil, ErrMissingZoneID
+ }
+
+ autoPaginate := true
+ if params.PerPage >= 1 || params.Page >= 1 {
+ autoPaginate = false
+ }
+
+ if params.PerPage < 1 {
+ params.PerPage = listZarazConfigHistoryDefaultPageSize
+ }
+
+ if params.Page < 1 {
+ params.Page = 1
+ }
+
+ var records []ZarazHistoryRecord
+ var lastResultInfo ResultInfo
+
+ for {
+ uri := buildURI(fmt.Sprintf("/zones/%s/settings/zaraz/v2/history", rc.Identifier), params)
+ res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+ if err != nil {
+ return []ZarazHistoryRecord{}, &ResultInfo{}, err
+ }
+ var listResponse ZarazConfigHistoryListResponse
+ err = json.Unmarshal(res, &listResponse)
+ if err != nil {
+ return []ZarazHistoryRecord{}, &ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+ }
+ records = append(records, listResponse.Result...)
+ lastResultInfo = listResponse.ResultInfo
+ params.ResultInfo = listResponse.ResultInfo.Next()
+ if params.ResultInfo.Done() || !autoPaginate {
+ break
+ }
+ }
+ return records, &lastResultInfo, nil
+}
+
+func (api *API) GetDefaultZarazConfig(ctx context.Context, rc *ResourceContainer) (ZarazConfigResponse, error) {
+ if rc.Identifier == "" {
+ return ZarazConfigResponse{}, ErrMissingZoneID
+ }
+
+ uri := fmt.Sprintf("/zones/%s/settings/zaraz/v2/default", rc.Identifier)
+ res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+ if err != nil {
+ return ZarazConfigResponse{}, err
+ }
+
+ var recordResp ZarazConfigResponse
+ err = json.Unmarshal(res, &recordResp)
+ if err != nil {
+ return ZarazConfigResponse{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
+ }
+
+ return recordResp, nil
+}
+
+func (api *API) ExportZarazConfig(ctx context.Context, rc *ResourceContainer) error {
+ if rc.Identifier == "" {
+ return ErrMissingZoneID
+ }
+
+ uri := fmt.Sprintf("/zones/%s/settings/zaraz/v2/export", rc.Identifier)
+ res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
+ if err != nil {
+ return err
+ }
+
+ var recordResp ZarazConfig
+ err = json.Unmarshal(res, &recordResp)
+ if err != nil {
+ return fmt.Errorf("%s: %w", errUnmarshalError, err)
+ }
+
+ return nil
+}
diff --git a/zaraz_test.go b/zaraz_test.go
new file mode 100644
index 00000000000..a59115e3efb
--- /dev/null
+++ b/zaraz_test.go
@@ -0,0 +1,741 @@
+package cloudflare
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "net/http"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+var trueValue bool = true
+var falseValue bool = false
+
+var expectedConfig ZarazConfig = ZarazConfig{
+ DebugKey: "cheese",
+ ZarazVersion: 44,
+ DataLayer: &trueValue,
+ Dlp: []any{},
+ HistoryChange: &trueValue,
+ Settings: ZarazConfigSettings{
+ AutoInjectScript: &trueValue,
+ },
+ Tools: map[string]ZarazTool{
+ "PBQr": {
+ BlockingTriggers: []string{},
+ Enabled: &trueValue,
+ DefaultFields: map[string]any{},
+ Name: "Custom HTML",
+ NeoEvents: []ZarazNeoEvent{
+ {
+ ActionType: "event",
+ BlockingTriggers: []string{},
+ Data: map[string]any{
+ "__zaraz_setting_name": "pageview1",
+ "htmlCode": "",
+ },
+ FiringTriggers: []string{"Pageview"},
+ },
+ },
+ Type: ZarazToolComponent,
+ DefaultPurpose: "rJJC",
+ Component: "html",
+ Permissions: []string{"execute_unsafe_scripts"},
+ Settings: map[string]any{},
+ },
+ },
+ Triggers: map[string]ZarazTrigger{
+ "Pageview": {
+ Name: "Pageview",
+ Description: "All page loads",
+ LoadRules: []ZarazTriggerRule{{Match: "{{ client.__zarazTrack }}", Op: "EQUALS", Value: "Pageview"}},
+ ExcludeRules: []ZarazTriggerRule{},
+ ClientRules: []any{},
+ System: ZarazPageload,
+ },
+ "TFOl": {
+ Name: "test",
+ Description: "",
+ LoadRules: []ZarazTriggerRule{{Id: "Kqsc", Match: "test", Op: "CONTAINS", Value: "test"}, {Id: "EDnV", Action: ZarazClickListener, Settings: ZarazRuleSettings{Selector: "test", Type: ZarazCSS}}},
+ ExcludeRules: []ZarazTriggerRule{},
+ },
+ },
+ Variables: map[string]ZarazVariable{
+ "jwIx": {
+ Name: "test",
+ Type: ZarazVarString,
+ Value: "sss",
+ },
+ "pAuL": {
+ Name: "test-worker-var",
+ Type: ZarazVarWorker,
+ Value: map[string]interface{}{
+ "escapedWorkerName": "worker-var-example",
+ "mutableId": "m.zpt3q__WyW-61WM2qwgGoBl4Nxg-sfBsaMhu9NayjwU",
+ "workerTag": "68aba570db9d4ec5b159624e2f7ad8bf",
+ },
+ },
+ },
+ Consent: ZarazConsent{
+ Enabled: &trueValue,
+ ButtonTextTranslations: ZarazButtonTextTranslations{
+ AcceptAll: map[string]string{"en": "Accept ALL"},
+ ConfirmMyChoices: map[string]string{"en": "YES!"},
+ RejectAll: map[string]string{"en": "Reject ALL"},
+ },
+ CompanyEmail: "email@example.com",
+ ConsentModalIntroHTMLWithTranslations: map[string]string{"en": "Lorem ipsum dolar set Amet?"},
+ CookieName: "zaraz-consent",
+ CustomCSS: ".test {\n color: red;\n}",
+ CustomIntroDisclaimerDismissed: &trueValue,
+ DefaultLanguage: "en",
+ HideModal: &falseValue,
+ PurposesWithTranslations: map[string]ZarazPurposeWithTranslations{
+ "rJJC": {
+ Description: map[string]string{"en": "Blah blah"},
+ Name: map[string]string{"en": "Analytics"},
+ Order: 0,
+ },
+ },
+ },
+}
+
+func TestGetZarazConfig(t *testing.T) {
+ setup()
+ defer teardown()
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
+
+ w.Header().Set("content-type", "application/json")
+
+ fmt.Fprint(w, `{
+ "errors": [],
+ "messages": [],
+ "success": true,
+ "result": {
+ "consent": {
+ "buttonTextTranslations": {
+ "accept_all": {
+ "en": "Accept ALL"
+ },
+ "confirm_my_choices": {
+ "en": "YES!"
+ },
+ "reject_all": {
+ "en": "Reject ALL"
+ }
+ },
+ "companyEmail": "email@example.com",
+ "consentModalIntroHTMLWithTranslations": {
+ "en": "Lorem ipsum dolar set Amet?"
+ },
+ "cookieName": "zaraz-consent",
+ "customCSS": ".test {\n color: red;\n}",
+ "customIntroDisclaimerDismissed": true,
+ "defaultLanguage": "en",
+ "enabled": true,
+ "hideModal": false,
+ "purposesWithTranslations": {
+ "rJJC": {
+ "description": {
+ "en": "Blah blah"
+ },
+ "name": {
+ "en": "Analytics"
+ },
+ "order": 0
+ }
+ }
+ },
+ "dataLayer": true,
+ "debugKey": "cheese",
+ "dlp": [],
+ "historyChange": true,
+ "invalidKey": "cheese",
+ "settings": {
+ "autoInjectScript": true
+ },
+ "tools": {
+ "PBQr": {
+ "blockingTriggers": [],
+ "component": "html",
+ "defaultFields": {},
+ "defaultPurpose": "rJJC",
+ "enabled": true,
+ "mode": {
+ "cloud": false,
+ "ignoreSPA": true,
+ "light": false,
+ "sample": false,
+ "segment": {
+ "end": 100,
+ "start": 0
+ },
+ "trigger": "pageload"
+ },
+ "name": "Custom HTML",
+ "neoEvents": [
+ {
+ "actionType": "event",
+ "blockingTriggers": [],
+ "data": {
+ "__zaraz_setting_name": "pageview1",
+ "htmlCode": ""
+ },
+ "firingTriggers": [
+ "Pageview"
+ ]
+ }
+ ],
+ "permissions": [
+ "execute_unsafe_scripts"
+ ],
+ "settings": {},
+ "type": "component"
+ }
+ },
+ "triggers": {
+ "Pageview": {
+ "clientRules": [],
+ "description": "All page loads",
+ "excludeRules": [],
+ "loadRules": [
+ {
+ "match": "{{ client.__zarazTrack }}",
+ "op": "EQUALS",
+ "value": "Pageview"
+ }
+ ],
+ "name": "Pageview",
+ "system": "pageload"
+ },
+ "TFOl": {
+ "description": "",
+ "excludeRules": [],
+ "loadRules": [
+ {
+ "id": "Kqsc",
+ "match": "test",
+ "op": "CONTAINS",
+ "value": "test"
+ },
+ {
+ "action": "clickListener",
+ "id": "EDnV",
+ "settings": {
+ "selector": "test",
+ "type": "css",
+ "waitForTags": 0
+ }
+ }
+ ],
+ "name": "test"
+ }
+ },
+ "variables": {
+ "jwIx": {
+ "name": "test",
+ "type": "string",
+ "value": "sss"
+ },
+ "pAuL": {
+ "name": "test-worker-var",
+ "type": "worker",
+ "value": {
+ "escapedWorkerName": "worker-var-example",
+ "mutableId": "m.zpt3q__WyW-61WM2qwgGoBl4Nxg-sfBsaMhu9NayjwU",
+ "workerTag": "68aba570db9d4ec5b159624e2f7ad8bf"
+ }
+ }
+ },
+ "zarazVersion": 44
+ }
+ }`)
+ }
+
+ mux.HandleFunc("/zones/"+testZoneID+"/settings/zaraz/v2/config", handler)
+
+ actual, err := client.GetZarazConfig(context.Background(), ZoneIdentifier(testZoneID))
+ require.NoError(t, err)
+
+ assert.Equal(t, expectedConfig, actual.Result)
+}
+
+func TestUpdateZarazConfig(t *testing.T) {
+ setup()
+ defer teardown()
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method)
+
+ w.Header().Set("content-type", "application/json")
+ fmt.Fprint(w, `{
+ "errors": [],
+ "messages": [],
+ "success": true,
+ "result": {
+ "consent": {
+ "buttonTextTranslations": {
+ "accept_all": {
+ "en": "Accept ALL"
+ },
+ "confirm_my_choices": {
+ "en": "YES!"
+ },
+ "reject_all": {
+ "en": "Reject ALL"
+ }
+ },
+ "companyEmail": "email@example.com",
+ "consentModalIntroHTMLWithTranslations": {
+ "en": "Lorem ipsum dolar set Amet?"
+ },
+ "cookieName": "zaraz-consent",
+ "customCSS": ".test {\n color: red;\n}",
+ "customIntroDisclaimerDismissed": true,
+ "defaultLanguage": "en",
+ "enabled": true,
+ "hideModal": false,
+ "purposesWithTranslations": {
+ "rJJC": {
+ "description": {
+ "en": "Blah blah"
+ },
+ "name": {
+ "en": "Analytics"
+ },
+ "order": 0
+ }
+ }
+ },
+ "dataLayer": true,
+ "debugKey": "butter",
+ "dlp": [],
+ "historyChange": true,
+ "invalidKey": "cheese",
+ "settings": {
+ "autoInjectScript": true
+ },
+ "tools": {
+ "PBQr": {
+ "blockingTriggers": [],
+ "component": "html",
+ "defaultFields": {},
+ "defaultPurpose": "rJJC",
+ "enabled": true,
+ "mode": {
+ "cloud": false,
+ "ignoreSPA": true,
+ "light": false,
+ "sample": false,
+ "segment": {
+ "end": 100,
+ "start": 0
+ },
+ "trigger": "pageload"
+ },
+ "name": "Custom HTML",
+ "neoEvents": [
+ {
+ "actionType": "event",
+ "blockingTriggers": [],
+ "data": {
+ "__zaraz_setting_name": "pageview1",
+ "htmlCode": ""
+ },
+ "firingTriggers": [
+ "Pageview"
+ ]
+ }
+ ],
+ "permissions": [
+ "execute_unsafe_scripts"
+ ],
+ "settings": {},
+ "type": "component"
+ }
+ },
+ "triggers": {
+ "Pageview": {
+ "clientRules": [],
+ "description": "All page loads",
+ "excludeRules": [],
+ "loadRules": [
+ {
+ "match": "{{ client.__zarazTrack }}",
+ "op": "EQUALS",
+ "value": "Pageview"
+ }
+ ],
+ "name": "Pageview",
+ "system": "pageload"
+ },
+ "TFOl": {
+ "description": "",
+ "excludeRules": [],
+ "loadRules": [
+ {
+ "id": "Kqsc",
+ "match": "test",
+ "op": "CONTAINS",
+ "value": "test"
+ },
+ {
+ "action": "clickListener",
+ "id": "EDnV",
+ "settings": {
+ "selector": "test",
+ "type": "css",
+ "waitForTags": 0
+ }
+ }
+ ],
+ "name": "test"
+ }
+ },
+ "variables": {
+ "jwIx": {
+ "name": "test",
+ "type": "string",
+ "value": "sss"
+ },
+ "pAuL": {
+ "name": "test-worker-var",
+ "type": "worker",
+ "value": {
+ "escapedWorkerName": "worker-var-example",
+ "mutableId": "m.zpt3q__WyW-61WM2qwgGoBl4Nxg-sfBsaMhu9NayjwU",
+ "workerTag": "68aba570db9d4ec5b159624e2f7ad8bf"
+ }
+ }
+ },
+ "zarazVersion": 44
+ }
+ }`)
+ }
+
+ mux.HandleFunc("/zones/"+testZoneID+"/settings/zaraz/v2/config", handler)
+ payload := UpdateZarazConfigParams{
+ DebugKey: "cheese",
+ ZarazVersion: 44,
+ DataLayer: &trueValue,
+ Dlp: []any{},
+ HistoryChange: &trueValue,
+ Settings: ZarazConfigSettings{
+ AutoInjectScript: &trueValue,
+ },
+ Tools: map[string]ZarazTool{
+ "PBQr": {
+ BlockingTriggers: []string{},
+ Enabled: &trueValue,
+ DefaultFields: map[string]any{},
+ Name: "Custom HTML",
+ NeoEvents: []ZarazNeoEvent{
+ {
+ ActionType: "event",
+ BlockingTriggers: []string{},
+ Data: map[string]any{
+ "__zaraz_setting_name": "pageview1",
+ "htmlCode": "",
+ },
+ FiringTriggers: []string{"Pageview"},
+ },
+ },
+ Type: ZarazToolComponent,
+ DefaultPurpose: "rJJC",
+ Component: "html",
+ Permissions: []string{"execute_unsafe_scripts"},
+ Settings: map[string]any{},
+ },
+ },
+ Triggers: map[string]ZarazTrigger{
+ "Pageview": {
+ Name: "Pageview",
+ Description: "All page loads",
+ LoadRules: []ZarazTriggerRule{{Match: "{{ client.__zarazTrack }}", Op: "EQUALS", Value: "Pageview"}},
+ ExcludeRules: []ZarazTriggerRule{},
+ ClientRules: []any{},
+ System: ZarazPageload,
+ },
+ "TFOl": {
+ Name: "test",
+ Description: "",
+ LoadRules: []ZarazTriggerRule{{Id: "Kqsc", Match: "test", Op: "CONTAINS", Value: "test"}, {Id: "EDnV", Action: ZarazClickListener, Settings: ZarazRuleSettings{Selector: "test", Type: ZarazCSS}}},
+ ExcludeRules: []ZarazTriggerRule{},
+ },
+ },
+ Variables: map[string]ZarazVariable{
+ "jwIx": {
+ Name: "test",
+ Type: ZarazVarString,
+ Value: "sss",
+ },
+ "pAuL": {
+ Name: "test-worker-var",
+ Type: ZarazVarWorker,
+ Value: map[string]interface{}{
+ "escapedWorkerName": "worker-var-example",
+ "mutableId": "m.zpt3q__WyW-61WM2qwgGoBl4Nxg-sfBsaMhu9NayjwU",
+ "workerTag": "68aba570db9d4ec5b159624e2f7ad8bf",
+ },
+ },
+ },
+ Consent: ZarazConsent{
+ Enabled: &trueValue,
+ ButtonTextTranslations: ZarazButtonTextTranslations{
+ AcceptAll: map[string]string{"en": "Accept ALL"},
+ ConfirmMyChoices: map[string]string{"en": "YES!"},
+ RejectAll: map[string]string{"en": "Reject ALL"},
+ },
+ CompanyEmail: "email@example.com",
+ ConsentModalIntroHTMLWithTranslations: map[string]string{"en": "Lorem ipsum dolar set Amet?"},
+ CookieName: "zaraz-consent",
+ CustomCSS: ".test {\n color: red;\n}",
+ CustomIntroDisclaimerDismissed: &trueValue,
+ DefaultLanguage: "en",
+ HideModal: &falseValue,
+ PurposesWithTranslations: map[string]ZarazPurposeWithTranslations{
+ "rJJC": {
+ Description: map[string]string{"en": "Blah blah"},
+ Name: map[string]string{"en": "Analytics"},
+ Order: 0,
+ },
+ },
+ },
+ }
+ payload.DebugKey = "butter" // Updating config
+ modifiedConfig := expectedConfig
+ modifiedConfig.DebugKey = "butter" // Updating config
+ expected := ZarazConfigResponse{
+ Result: modifiedConfig,
+ }
+
+ actual, err := client.UpdateZarazConfig(context.Background(), ZoneIdentifier(testZoneID), payload)
+ require.NoError(t, err)
+
+ assert.Equal(t, expected.Result, actual.Result)
+}
+
+func TestGetZarazWorkflow(t *testing.T) {
+ setup()
+ defer teardown()
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
+
+ w.Header().Set("Content-Type", "application/json")
+ fmt.Fprint(w, `{
+ "errors": [],
+ "messages": [],
+ "success": true,
+ "result": "realtime"
+ }`)
+ }
+
+ mux.HandleFunc("/zones/"+testZoneID+"/settings/zaraz/v2/workflow", handler)
+ want := ZarazWorkflowResponse{
+ Result: "realtime",
+ Response: Response{
+ Success: true,
+ Messages: []ResponseInfo{},
+ Errors: []ResponseInfo{},
+ },
+ }
+
+ actual, err := client.GetZarazWorkflow(context.Background(), ZoneIdentifier(testZoneID))
+
+ require.NoError(t, err)
+
+ assert.Equal(t, want, actual)
+}
+
+func TestUpdateZarazWorkflow(t *testing.T) {
+ setup()
+ defer teardown()
+
+ payload := UpdateZarazWorkflowParams{
+ Workflow: "realtime",
+ }
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, http.MethodPut, r.Method, "Expected method 'PUT', got %s", r.Method)
+ body, _ := io.ReadAll(r.Body)
+ bodyString := string(body)
+ assert.Equal(t, fmt.Sprintf("\"%s\"", payload.Workflow), bodyString)
+
+ w.Header().Set("Content-Type", "application/json")
+ fmt.Fprint(w, `{
+ "errors": [],
+ "messages": [],
+ "success": true,
+ "result": "realtime"
+ }`)
+ }
+
+ mux.HandleFunc("/zones/"+testZoneID+"/settings/zaraz/v2/workflow", handler)
+ want := ZarazWorkflowResponse{
+ Result: "realtime",
+ Response: Response{
+ Success: true,
+ Messages: []ResponseInfo{},
+ Errors: []ResponseInfo{},
+ },
+ }
+
+ actual, err := client.UpdateZarazWorkflow(context.Background(), ZoneIdentifier(testZoneID), payload)
+
+ require.NoError(t, err)
+
+ assert.Equal(t, want, actual)
+}
+
+func TestPublishZarazConfig(t *testing.T) {
+ setup()
+ defer teardown()
+
+ payload := PublishZarazConfigParams{
+ Description: "test description",
+ }
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, http.MethodPost, r.Method, "Expected method 'POST', got %s", r.Method)
+ body, _ := io.ReadAll(r.Body)
+ bodyString := string(body)
+ assert.Equal(t, fmt.Sprintf("\"%s\"", payload.Description), bodyString)
+
+ w.Header().Set("Content-Type", "application/json")
+ fmt.Fprint(w, `{
+ "errors": [],
+ "messages": [],
+ "success": true,
+ "result": "Config has been published successfully"
+ }`)
+ }
+
+ mux.HandleFunc("/zones/"+testZoneID+"/settings/zaraz/v2/publish", handler)
+ want := ZarazPublishResponse{
+ Result: "Config has been published successfully",
+ Response: Response{
+ Success: true,
+ Messages: []ResponseInfo{},
+ Errors: []ResponseInfo{},
+ },
+ }
+
+ actual, err := client.PublishZarazConfig(context.Background(), ZoneIdentifier(testZoneID), payload)
+
+ require.NoError(t, err)
+
+ assert.Equal(t, want, actual)
+}
+
+func TestGetZarazConfigHistoryList(t *testing.T) {
+ setup()
+ defer teardown()
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
+
+ w.Header().Set("content-type", "application/json")
+ fmt.Fprint(w, `{
+ "result": [
+ {
+ "createdAt": "2023-01-01T05:20:00Z",
+ "description": "test 1",
+ "id": 1005736,
+ "updatedAt": "2023-01-01T05:20:00Z",
+ "userId": "9ceddf6f117afe04c64716c83468d3a4"
+ },
+ {
+ "createdAt": "2023-01-01T05:20:00Z",
+ "description": "test 2",
+ "id": 1005735,
+ "updatedAt": "2023-01-01T05:20:00Z",
+ "userId": "9ceddf6f117afe04c64716c83468d3a4"
+ }
+ ],
+ "success": true,
+ "errors": [],
+ "messages": [],
+ "result_info": {
+ "page": 1,
+ "per_page": 2,
+ "count": 2,
+ "total_count": 8
+ }
+ }`)
+ }
+
+ mux.HandleFunc("/zones/"+testZoneID+"/settings/zaraz/v2/history", handler)
+ createdAt, _ := time.Parse(time.RFC3339, "2023-01-01T05:20:00Z")
+ updatedAt, _ := time.Parse(time.RFC3339, "2023-01-01T05:20:00Z")
+ want := []ZarazHistoryRecord{
+ {
+ CreatedAt: &createdAt,
+ Description: "test 1",
+ ID: 1005736,
+ UpdatedAt: &updatedAt,
+ UserID: "9ceddf6f117afe04c64716c83468d3a4",
+ },
+ {
+ CreatedAt: &createdAt,
+ Description: "test 2",
+ ID: 1005735,
+ UpdatedAt: &updatedAt,
+ UserID: "9ceddf6f117afe04c64716c83468d3a4",
+ },
+ }
+
+ actual, _, err := client.ListZarazConfigHistory(context.Background(), ZoneIdentifier(testZoneID), ListZarazConfigHistoryParams{
+ ResultInfo: ResultInfo{
+ PerPage: 2,
+ },
+ })
+
+ require.NoError(t, err)
+
+ assert.Equal(t, want, actual)
+}
+
+func TestGetDefaultZarazConfig(t *testing.T) {
+ setup()
+ defer teardown()
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
+
+ w.Header().Set("content-type", "text/plain")
+ fmt.Fprint(w, `{
+ "someTestKeyThatRepsTheConfig": "test"
+ }`)
+ }
+
+ mux.HandleFunc("/zones/"+testZoneID+"/settings/zaraz/v2/default", handler)
+
+ _, err := client.GetDefaultZarazConfig(context.Background(), ZoneIdentifier(testZoneID))
+ require.NoError(t, err)
+}
+
+func TestExportZarazConfig(t *testing.T) {
+ setup()
+ defer teardown()
+
+ handler := func(w http.ResponseWriter, r *http.Request) {
+ assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
+
+ w.Header().Set("content-type", "text/plain")
+ fmt.Fprint(w, `{
+ "someTestKeyThatRepsTheConfig": "test"
+ }`)
+ }
+
+ mux.HandleFunc("/zones/"+testZoneID+"/settings/zaraz/v2/export", handler)
+
+ err := client.ExportZarazConfig(context.Background(), ZoneIdentifier(testZoneID))
+ require.NoError(t, err)
+}