@@ -25,19 +25,21 @@ func (err *MixpanelError) Error() string {
2525}
2626
2727type ErrTrackFailed struct {
28- Body string
29- Resp * http.Response
28+ Message string
3029}
3130
3231func (err * ErrTrackFailed ) Error () string {
33- return fmt .Sprintf ("Mixpanel did not return 1 when tracking: %s" , err .Body )
32+ return fmt .Sprintf ("mixpanel did not return 1 when tracking: %s" , err .Message )
3433}
3534
3635// The Mixapanel struct store the mixpanel endpoint and the project token
3736type Mixpanel interface {
38- // Create a mixpanel event
37+ // Create a mixpanel event using the track api
3938 Track (distinctId , eventName string , e * Event ) error
4039
40+ // Create a mixpanel event using the import api
41+ Import (distinctId , eventName string , e * Event ) error
42+
4143 // Set properties for a mixpanel user.
4244 // Deprecated: Use UpdateUser instead
4345 Update (distinctId string , u * Update ) error
@@ -48,13 +50,15 @@ type Mixpanel interface {
4850 // Set properties for a mixpanel group.
4951 UpdateGroup (groupKey , groupId string , u * Update ) error
5052
53+ // Create an alias for an existing distinct id
5154 Alias (distinctId , newId string ) error
5255}
5356
5457// The Mixapanel struct store the mixpanel endpoint and the project token
5558type mixpanel struct {
5659 Client * http.Client
5760 Token string
61+ Secret string
5862 ApiURL string
5963}
6064
@@ -88,7 +92,7 @@ type Update struct {
8892 Properties map [string ]interface {}
8993}
9094
91- // Track create a events to current distinct id
95+ // Alias create an alias for an existing distinct id
9296func (m * mixpanel ) Alias (distinctId , newId string ) error {
9397 props := map [string ]interface {}{
9498 "token" : m .Token ,
@@ -104,7 +108,7 @@ func (m *mixpanel) Alias(distinctId, newId string) error {
104108 return m .send ("track" , params , false )
105109}
106110
107- // Track create a events to current distinct id
111+ // Track create an event for an existing distinct id
108112func (m * mixpanel ) Track (distinctId , eventName string , e * Event ) error {
109113 props := map [string ]interface {}{
110114 "token" : m .Token ,
@@ -131,6 +135,36 @@ func (m *mixpanel) Track(distinctId, eventName string, e *Event) error {
131135 return m .send ("track" , params , autoGeolocate )
132136}
133137
138+ // Import create an event for an existing distinct id
139+ // See https://developer.mixpanel.com/docs/importing-old-events
140+ func (m * mixpanel ) Import (distinctId , eventName string , e * Event ) error {
141+ props := map [string ]interface {}{
142+ "token" : m .Token ,
143+ "distinct_id" : distinctId ,
144+ }
145+ if e .IP != "" {
146+ props ["ip" ] = e .IP
147+ }
148+ if e .Timestamp != nil {
149+ props ["time" ] = e .Timestamp .Unix ()
150+ }
151+
152+ for key , value := range e .Properties {
153+ props [key ] = value
154+ }
155+
156+ params := map [string ]interface {}{
157+ "event" : eventName ,
158+ "properties" : props ,
159+ }
160+
161+ autoGeolocate := e .IP == ""
162+
163+ return m .send ("import" , params , autoGeolocate )
164+ }
165+
166+ // Update updates a user in mixpanel. See
167+ // https://mixpanel.com/help/reference/http#people-analytics-updates
134168// Deprecated: Use UpdateUser instead
135169func (m * mixpanel ) Update (distinctId string , u * Update ) error {
136170 return m .UpdateUser (distinctId , u )
@@ -185,7 +219,7 @@ func (m *mixpanel) send(eventType string, params interface{}, autoGeolocate bool
185219 return err
186220 }
187221
188- url := m .ApiURL + "/" + eventType + "?data=" + m .to64 (data )
222+ url := m .ApiURL + "/" + eventType + "?data=" + m .to64 (data ) + "&verbose=1"
189223
190224 if autoGeolocate {
191225 url += "&ip=1"
@@ -195,7 +229,11 @@ func (m *mixpanel) send(eventType string, params interface{}, autoGeolocate bool
195229 return & MixpanelError {URL : url , Err : err }
196230 }
197231
198- resp , err := m .Client .Get (url )
232+ req , _ := http .NewRequest ("GET" , url , nil )
233+ if m .Secret != "" {
234+ req .SetBasicAuth (m .Secret , "" )
235+ }
236+ resp , err := m .Client .Do (req )
199237
200238 if err != nil {
201239 return wrapErr (err )
@@ -209,8 +247,17 @@ func (m *mixpanel) send(eventType string, params interface{}, autoGeolocate bool
209247 return wrapErr (bodyErr )
210248 }
211249
212- if strBody := string (body ); strBody != "1" && strBody != "1\n " {
213- return wrapErr (& ErrTrackFailed {Body : strBody , Resp : resp })
250+ type verboseResponse struct {
251+ Error string `json:"error"`
252+ Status int `json:"status"`
253+ }
254+
255+ var jsonBody verboseResponse
256+ json .Unmarshal (body , & jsonBody )
257+
258+ if jsonBody .Status != 1 {
259+ errMsg := fmt .Sprintf ("error=%s; status=%d; httpCode=%d" , jsonBody .Error , jsonBody .Status , resp .StatusCode )
260+ return wrapErr (& ErrTrackFailed {Message : errMsg })
214261 }
215262
216263 return nil
@@ -222,16 +269,28 @@ func New(token, apiURL string) Mixpanel {
222269 return NewFromClient (http .DefaultClient , token , apiURL )
223270}
224271
225- // Creates a client instance using the specified client instance. This is useful
272+ // NewWithSecret returns the client instance using a secret.If apiURL is blank,
273+ // the default will be used ("https://api.mixpanel.com").
274+ func NewWithSecret (token , secret , apiURL string ) Mixpanel {
275+ return NewFromClientWithSecret (http .DefaultClient , token , secret , apiURL )
276+ }
277+
278+ // NewFromClient creates a client instance using the specified client instance. This is useful
226279// when using a proxy.
227280func NewFromClient (c * http.Client , token , apiURL string ) Mixpanel {
281+ return NewFromClientWithSecret (c , token , "" , apiURL )
282+ }
283+
284+ // NewFromClientWithSecret creates a client instance using the specified client instance and secret.
285+ func NewFromClientWithSecret (c * http.Client , token , secret , apiURL string ) Mixpanel {
228286 if apiURL == "" {
229287 apiURL = "https://api.mixpanel.com"
230288 }
231289
232290 return & mixpanel {
233291 Client : c ,
234292 Token : token ,
293+ Secret : secret ,
235294 ApiURL : apiURL ,
236295 }
237296}
0 commit comments