{satellite/console, web/satellite}: send analytics if invitee signs up
send analytics event if project invite link is clicked and if user signs up. github issue: https://github.com/storj/storj/issues/5190 Change-Id: I41eee5e679a84b9ec325815655684a98624d5656
This commit is contained in:
parent
81d49ada06
commit
a2d37bc69a
@ -15,6 +15,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
eventInviteLinkClicked = "Invite Link Clicked"
|
||||
eventInviteLinkSignup = "Invite Link Signup"
|
||||
eventAccountCreated = "Account Created"
|
||||
eventSignedIn = "Signed In"
|
||||
eventProjectCreated = "Project Created"
|
||||
@ -734,3 +736,35 @@ func (service *Service) TrackExpiredCreditRemoved(userID uuid.UUID, customerID,
|
||||
Properties: props,
|
||||
})
|
||||
}
|
||||
|
||||
// TrackInviteLinkSignup sends an "Invite Link Signup" event to Segment.
|
||||
func (service *Service) TrackInviteLinkSignup(inviter, invitee string) {
|
||||
if !service.config.Enabled {
|
||||
return
|
||||
}
|
||||
|
||||
props := segment.NewProperties()
|
||||
props.Set("inviter", inviter)
|
||||
props.Set("invitee", invitee)
|
||||
|
||||
service.enqueueMessage(segment.Track{
|
||||
Event: service.satelliteName + " " + eventInviteLinkSignup,
|
||||
Properties: props,
|
||||
})
|
||||
}
|
||||
|
||||
// TrackInviteLinkClicked sends an "Invite Link Clicked" event to Segment.
|
||||
func (service *Service) TrackInviteLinkClicked(inviter, invitee string) {
|
||||
if !service.config.Enabled {
|
||||
return
|
||||
}
|
||||
|
||||
props := segment.NewProperties()
|
||||
props.Set("inviter", inviter)
|
||||
props.Set("invitee", invitee)
|
||||
|
||||
service.enqueueMessage(segment.Track{
|
||||
Event: service.satelliteName + " " + eventInviteLinkClicked,
|
||||
Properties: props,
|
||||
})
|
||||
}
|
||||
|
@ -319,6 +319,26 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
invites, err := a.service.GetInvitesByEmail(ctx, registerData.Email)
|
||||
if err != nil {
|
||||
a.log.Error("Could not get invitations", zap.String("email", registerData.Email), zap.Error(err))
|
||||
} else if len(invites) > 0 {
|
||||
var firstInvite console.ProjectInvitation
|
||||
for _, inv := range invites {
|
||||
if inv.InviterID != nil && (firstInvite.CreatedAt.IsZero() || inv.CreatedAt.Before(firstInvite.CreatedAt)) {
|
||||
firstInvite = inv
|
||||
}
|
||||
}
|
||||
if firstInvite.InviterID != nil {
|
||||
inviter, err := a.service.GetUser(ctx, *firstInvite.InviterID)
|
||||
if err != nil {
|
||||
a.log.Error("Error getting inviter info", zap.String("ID", firstInvite.InviterID.String()), zap.Error(err))
|
||||
} else {
|
||||
a.analytics.TrackInviteLinkSignup(inviter.Email, registerData.Email)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// see if referrer was provided in URL query, otherwise use the Referer header in the request.
|
||||
referrer := r.URL.Query().Get("referrer")
|
||||
if referrer == "" {
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
@ -26,6 +27,7 @@ import (
|
||||
|
||||
"storj.io/common/testcontext"
|
||||
"storj.io/common/testrand"
|
||||
"storj.io/common/uuid"
|
||||
"storj.io/storj/private/post"
|
||||
"storj.io/storj/private/testplanet"
|
||||
"storj.io/storj/satellite"
|
||||
@ -151,6 +153,82 @@ func TestAuth_Register(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuth_RegisterWithInvitation(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 1,
|
||||
Reconfigure: testplanet.Reconfigure{
|
||||
Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
|
||||
config.Console.OpenRegistrationEnabled = true
|
||||
config.Console.RateLimit.Burst = 10
|
||||
config.Mail.AuthType = "nomail"
|
||||
},
|
||||
},
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
for i := 0; i < 2; i++ {
|
||||
email := fmt.Sprintf("user%d@test.test", i)
|
||||
// test with nil and non-nil inviter ID to make sure nil pointer dereference doesn't occur
|
||||
// since nil ID is technically possible
|
||||
var inviter *uuid.UUID
|
||||
if i == 1 {
|
||||
id := planet.Uplinks[0].Projects[0].Owner.ID
|
||||
inviter = &id
|
||||
}
|
||||
_, err := planet.Satellites[0].API.DB.Console().ProjectInvitations().Upsert(ctx, &console.ProjectInvitation{
|
||||
ProjectID: planet.Uplinks[0].Projects[0].ID,
|
||||
Email: email,
|
||||
InviterID: inviter,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
registerData := struct {
|
||||
FullName string `json:"fullName"`
|
||||
ShortName string `json:"shortName"`
|
||||
Email string `json:"email"`
|
||||
Partner string `json:"partner"`
|
||||
UserAgent string `json:"userAgent"`
|
||||
Password string `json:"password"`
|
||||
SecretInput string `json:"secret"`
|
||||
ReferrerUserID string `json:"referrerUserId"`
|
||||
IsProfessional bool `json:"isProfessional"`
|
||||
Position string `json:"Position"`
|
||||
CompanyName string `json:"CompanyName"`
|
||||
EmployeeCount string `json:"EmployeeCount"`
|
||||
SignupPromoCode string `json:"signupPromoCode"`
|
||||
}{
|
||||
FullName: "testuser",
|
||||
ShortName: "test",
|
||||
Email: email,
|
||||
Password: "abc123",
|
||||
IsProfessional: true,
|
||||
Position: "testposition",
|
||||
CompanyName: "companytestname",
|
||||
EmployeeCount: "0",
|
||||
SignupPromoCode: "STORJ50",
|
||||
}
|
||||
|
||||
jsonBody, err := json.Marshal(registerData)
|
||||
require.NoError(t, err)
|
||||
|
||||
url := planet.Satellites[0].ConsoleURL() + "/api/v0/auth/register"
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(jsonBody))
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
result, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
err = result.Body.Close()
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
require.Equal(t, http.StatusOK, result.StatusCode)
|
||||
require.Len(t, planet.Satellites, 1)
|
||||
// this works only because we configured 'nomail' above. Mail send simulator won't click to activation link.
|
||||
_, users, err := planet.Satellites[0].API.Console.Service.GetUserByEmailWithUnverified(ctx, registerData.Email)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, users, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestDeleteAccount(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
log := testplanet.NewLogger(t)
|
||||
|
@ -927,6 +927,8 @@ func (server *Server) handleInvited(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
params.Add("inviter", name)
|
||||
params.Add("inviter_email", inviter.Email)
|
||||
|
||||
server.analytics.TrackInviteLinkClicked(inviter.Email, invite.Email)
|
||||
}
|
||||
|
||||
proj, err := server.service.GetProjectNoAuth(ctx, invite.ProjectID)
|
||||
|
@ -3782,6 +3782,13 @@ func (s *Service) IsProjectInvitationExpired(invite *ProjectInvitation) bool {
|
||||
return time.Now().After(invite.CreatedAt.Add(s.config.ProjectInvitationExpiration))
|
||||
}
|
||||
|
||||
// GetInvitesByEmail returns project invites by email.
|
||||
func (s *Service) GetInvitesByEmail(ctx context.Context, email string) (invites []ProjectInvitation, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
return s.store.ProjectInvitations().GetByEmail(ctx, email)
|
||||
}
|
||||
|
||||
// GetInviteByToken returns a project invite given an invite token.
|
||||
func (s *Service) GetInviteByToken(ctx context.Context, token string) (invite *ProjectInvitation, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
Loading…
Reference in New Issue
Block a user