diff --git a/README.md b/README.md index 10f4259..27f24ab 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ You can view the generated [documentation here](https://godoc.org/github.com/ton - [x] [Goals](https://docs.tonicpow.com/#316b77ab-4900-4f3d-96a7-e67c00af10ca) - [x] [Links](https://docs.tonicpow.com/#ee74c3ce-b4df-4d57-abf2-ccf3a80e4e1e) - [x] [Visitors](https://docs.tonicpow.com/#d0d9055a-0c92-4f55-a370-762d44acf801) + - [x] [Conversions](https://docs.tonicpow.com/#75c837d5-3336-4d87-a686-d80c6f8938b9) ## Examples & Tests All unit tests and [examples](tonicpow_test.go) run via [Travis CI](https://travis-ci.org/tonicpow/go-tonicpow) and uses [Go version 1.13.x](https://golang.org/doc/go1.13). View the [deployment configuration file](.travis.yml). diff --git a/conversions.go b/conversions.go new file mode 100644 index 0000000..b3059ec --- /dev/null +++ b/conversions.go @@ -0,0 +1,143 @@ +package tonicpow + +import ( + "encoding/json" + "fmt" + "net/http" +) + +// CreateConversionByGoalID will fire a conversion for a given goal id, if successful it will make a new Conversion +// +// For more information: https://docs.tonicpow.com/#caeffdd5-eaad-4fc8-ac01-8288b50e8e27 +func (c *Client) CreateConversionByGoalID(goalID uint64, tncpwSession, additionalData string, delayInMinutes int64) (conversion *Conversion, err error) { + + // Must have a name + if goalID == 0 { + err = fmt.Errorf("missing field: %s", fieldID) + return + } + + // Must have a session guid + if len(tncpwSession) == 0 { + err = fmt.Errorf("missing field: %s", fieldVisitorSessionGUID) + return + } + + // Start the post data + data := map[string]string{fieldGoalID: fmt.Sprintf("%d", goalID), fieldVisitorSessionGUID: tncpwSession, fieldAdditionalData: additionalData, fieldDelayInMinutes: fmt.Sprintf("%d", delayInMinutes)} + + // Fire the request + var response string + if response, err = c.request(modelConversion, http.MethodPost, data, ""); err != nil { + return + } + + // Only a 201 is treated as a success + if err = c.error(http.StatusCreated, response); err != nil { + return + } + + // Convert model response + err = json.Unmarshal([]byte(response), &conversion) + return +} + +// CreateConversionByGoalName will fire a conversion for a given goal name, if successful it will make a new Conversion +// +// For more information: https://docs.tonicpow.com/#d19c9850-3832-45b2-b880-3ef2f3b7dc37 +func (c *Client) CreateConversionByGoalName(goalName, tncpwSession, additionalData string, delayInMinutes int64) (conversion *Conversion, err error) { + + // Must have a name + if len(goalName) == 0 { + err = fmt.Errorf("missing field: %s", fieldName) + return + } + + // Must have a session guid + if len(tncpwSession) == 0 { + err = fmt.Errorf("missing field: %s", fieldVisitorSessionGUID) + return + } + + // Start the post data + data := map[string]string{fieldName: goalName, fieldVisitorSessionGUID: tncpwSession, fieldAdditionalData: additionalData, fieldDelayInMinutes: fmt.Sprintf("%d", delayInMinutes)} + + // Fire the request + var response string + if response, err = c.request(modelConversion, http.MethodPost, data, ""); err != nil { + return + } + + // Only a 201 is treated as a success + if err = c.error(http.StatusCreated, response); err != nil { + return + } + + // Convert model response + err = json.Unmarshal([]byte(response), &conversion) + return +} + +// CreateConversionByUserID will fire a conversion for a given goal and user id, if successful it will make a new Conversion +// +// For more information: https://docs.tonicpow.com/#d724f762-329e-473d-bdc4-aebc19dd9ea8 +func (c *Client) CreateConversionByUserID(goalID, userID uint64, additionalData string, delayInMinutes int64) (conversion *Conversion, err error) { + + // Must have a name + if goalID == 0 { + err = fmt.Errorf("missing field: %s", fieldID) + return + } + + // Must have a user id + if userID == 0 { + err = fmt.Errorf("missing field: %s", fieldUserID) + return + } + + // Start the post data + data := map[string]string{fieldGoalID: fmt.Sprintf("%d", goalID), fieldUserID: fmt.Sprintf("%d", userID), fieldAdditionalData: additionalData, fieldDelayInMinutes: fmt.Sprintf("%d", delayInMinutes)} + + // Fire the request + var response string + if response, err = c.request(modelConversion, http.MethodPost, data, ""); err != nil { + return + } + + // Only a 201 is treated as a success + if err = c.error(http.StatusCreated, response); err != nil { + return + } + + // Convert model response + err = json.Unmarshal([]byte(response), &conversion) + return +} + +// GetConversion will get an existing conversion +// This will return an error if the goal is not found (404) +// +// For more information: https://docs.tonicpow.com/#fce465a1-d8d5-442d-be22-95169170167e +func (c *Client) GetConversion(conversionID uint64) (conversion *Conversion, err error) { + + // Must have an id + if conversionID == 0 { + err = fmt.Errorf("missing field: %s", fieldID) + return + } + + // Fire the request + var response string + if response, err = c.request(fmt.Sprintf("%s/details/%d", modelConversion, conversionID), http.MethodGet, nil, ""); err != nil { + return + } + + // Only a 200 is treated as a success + if err = c.error(http.StatusOK, response); err != nil { + return + } + + // Convert model response + err = json.Unmarshal([]byte(response), &conversion) + return +} diff --git a/definitions.go b/definitions.go index 26c7a92..c238c3d 100644 --- a/definitions.go +++ b/definitions.go @@ -10,7 +10,9 @@ const ( fieldAdvertiserProfileID = "advertiser_profile_id" fieldApiKey = "api_key" fieldCampaignID = "campaign_id" + fieldDelayInMinutes = "delay_in_minutes" fieldEmail = "email" + fieldGoalID = "goal_id" fieldID = "id" fieldLinkID = "link_id" fieldName = "name" @@ -26,6 +28,7 @@ const ( // Model names (used for request endpoints) modelAdvertiser = "advertisers" modelCampaign = "campaigns" + modelConversion = "conversions" modelGoal = "goals" modelLink = "links" modelUser = "users" @@ -133,15 +136,18 @@ type Goal struct { Title string `json:"title,omitempty"` } -// Conversion is the result of goal.Convert() +// Conversion is the response of getting a conversion // -// For more information: https://docs.tonicpow.com/#caeffdd5-eaad-4fc8-ac01-8288b50e8e27 +// For more information: https://docs.tonicpow.com/#75c837d5-3336-4d87-a686-d80c6f8938b9 type Conversion struct { AdditionalData string `json:"additional_data,omitempty"` - ConversionTxID string `json:"conversion_tx_id,omitempty"` + Amount uint64 `json:"amount,omitempty"` GoalID uint64 `json:"goal_id,omitempty"` GoalName string `json:"goal_name,omitempty"` - UserID string `json:"user_id,omitempty"` + ID uint64 `json:"ID,omitempty"` + PayoutAfter string `json:"payout_after,omitempty"` + Status string `json:"status,omitempty"` + TxID string `json:"tx_id,omitempty"` } // Link is the link model (child of User) (relates Campaign to User) diff --git a/examples/examples.go b/examples/examples.go index e73b752..8d1704b 100644 --- a/examples/examples.go +++ b/examples/examples.go @@ -227,7 +227,7 @@ func main() { CampaignID: campaign.ID, Description: "Bring leads and get paid!", Name: "new-lead-landing-page", - PayoutRate: 0.50, + PayoutRate: 0.02, PayoutType: "flat", Title: "Landing Page Leads", } @@ -295,6 +295,46 @@ func main() { if visitorSession, err = getVisitorSession(visitorSession.TncpwSession); err != nil { os.Exit(1) } + + log.Printf("visitor session found: %s", visitorSession.TncpwSession) + + // + // Example: Fire a conversion on a goal (by user id) + // + var newConversion *tonicpow.Conversion + if newConversion, err = TonicPowAPI.CreateConversionByUserID(goal.ID, user.ID, "", 5); err != nil { + os.Exit(1) + } + + log.Printf("successful conversion event: %d", newConversion.ID) + + // + // Example: Fire a conversion on a goal (by visitor) + // + if newConversion, err = TonicPowAPI.CreateConversionByGoalID(goal.ID, visitorSession.TncpwSession, "", 10); err != nil { + os.Exit(1) + } + + log.Printf("successful conversion event: %d payout after: %s", newConversion.ID, newConversion.PayoutAfter) + + // + // Example: Get conversion + // + var conversion *tonicpow.Conversion + if conversion, err = TonicPowAPI.GetConversion(newConversion.ID); err != nil { + os.Exit(1) + } + + log.Printf("got conversion: %d", conversion.ID) + + /*if newConversion, err = TonicPowAPI.CreateConversionByUserID(1, 1, "", 0); err != nil { + os.Exit(1) + }*/ + + /*if newConversion, err = TonicPowAPI.CreateConversionByUserID(1, 1, "", 1); err != nil { + os.Exit(1) + }*/ + } // diff --git a/goals.go b/goals.go index 269824e..328f8ad 100644 --- a/goals.go +++ b/goals.go @@ -99,111 +99,3 @@ func (c *Client) UpdateGoal(goal *Goal, userSessionToken string) (updatedGoal *G err = json.Unmarshal([]byte(response), &updatedGoal) return } - -// ConvertGoalByID will fire a conversion for a given goal id, if successful it will make a new Conversion -// -// For more information: https://docs.tonicpow.com/#caeffdd5-eaad-4fc8-ac01-8288b50e8e27 -func (c *Client) ConvertGoalByID(goalID uint64, tncpwSession, additionalData string) (conversion *Conversion, err error) { - - // Must have a name - if goalID == 0 { - err = fmt.Errorf("missing field: %s", fieldID) - return - } - - // Must have a session guid - if len(tncpwSession) == 0 { - err = fmt.Errorf("missing field: %s", fieldVisitorSessionGUID) - return - } - - // Start the post data - data := map[string]string{fieldID: fmt.Sprintf("%d", goalID), fieldVisitorSessionGUID: tncpwSession, fieldAdditionalData: additionalData} - - // Fire the request - var response string - if response, err = c.request(fmt.Sprintf("%s/convert", modelGoal), http.MethodPost, data, ""); err != nil { - return - } - - // Only a 201 is treated as a success - if err = c.error(http.StatusCreated, response); err != nil { - return - } - - // Convert model response - err = json.Unmarshal([]byte(response), &conversion) - return -} - -// ConvertGoalByName will fire a conversion for a given goal name, if successful it will make a new Conversion -// -// For more information: https://docs.tonicpow.com/#d19c9850-3832-45b2-b880-3ef2f3b7dc37 -func (c *Client) ConvertGoalByName(goalName, tncpwSession, additionalData string) (conversion *Conversion, err error) { - - // Must have a name - if len(goalName) == 0 { - err = fmt.Errorf("missing field: %s", fieldName) - return - } - - // Must have a session guid - if len(tncpwSession) == 0 { - err = fmt.Errorf("missing field: %s", fieldVisitorSessionGUID) - return - } - - // Start the post data - data := map[string]string{fieldName: goalName, fieldVisitorSessionGUID: tncpwSession, fieldAdditionalData: additionalData} - - // Fire the request - var response string - if response, err = c.request(fmt.Sprintf("%s/convert", modelGoal), http.MethodPost, data, ""); err != nil { - return - } - - // Only a 201 is treated as a success - if err = c.error(http.StatusCreated, response); err != nil { - return - } - - // Convert model response - err = json.Unmarshal([]byte(response), &conversion) - return -} - -// ConvertGoalByUserID will fire a conversion for a given goal and user id, if successful it will make a new Conversion -// -// For more information: https://docs.tonicpow.com/#d724f762-329e-473d-bdc4-aebc19dd9ea8 -func (c *Client) ConvertGoalByUserID(goalID, userID uint64, additionalData string) (conversion *Conversion, err error) { - - // Must have a name - if goalID == 0 { - err = fmt.Errorf("missing field: %s", fieldID) - return - } - - // Must have a user id - if userID == 0 { - err = fmt.Errorf("missing field: %s", fieldUserID) - return - } - - // Start the post data - data := map[string]string{fieldID: fmt.Sprintf("%d", goalID), fieldUserID: fmt.Sprintf("%d", userID), fieldAdditionalData: additionalData} - - // Fire the request - var response string - if response, err = c.request(fmt.Sprintf("%s/convert", modelGoal), http.MethodPost, data, ""); err != nil { - return - } - - // Only a 201 is treated as a success - if err = c.error(http.StatusCreated, response); err != nil { - return - } - - // Convert model response - err = json.Unmarshal([]byte(response), &conversion) - return -}