Skip to content

Commit

Permalink
Fix campaigns
Browse files Browse the repository at this point in the history
Fixes #613
  • Loading branch information
arp242 committed Oct 17, 2022
1 parent 24f4413 commit fff99bc
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 27 deletions.
5 changes: 3 additions & 2 deletions campaign.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ func (c *Campaign) Insert(ctx context.Context) error {
return errors.Wrap(err, "Campaign.Insert")
}

err = zdb.Exec(ctx, `insert into campaigns (site_id, name) values (?, ?)`, MustGetSite(ctx).ID, c.Name)
c.ID, err = zdb.InsertID(ctx, "campaign_id",
`insert into campaigns (site_id, name) values (?, ?)`, MustGetSite(ctx).ID, c.Name)
if err != nil {
return errors.Wrap(err, "Campaign.Insert")
}
Expand All @@ -51,7 +52,7 @@ func (c *Campaign) ByName(ctx context.Context, name string) error {
return nil
}

err := zdb.Get(ctx, c, `select * from campaigns where site_id=? and name=?`,
err := zdb.Get(ctx, c, `select * from campaigns where site_id=? and lower(name)=lower(?)`,
MustGetSite(ctx).ID, name)
if err != nil {
return errors.Wrap(err, "Campaign.ByName")
Expand Down
12 changes: 7 additions & 5 deletions cron/campaign_stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func updateCampaignStats(ctx context.Context, hits []goatcounter.Hit) error {
day string
campaignID int64
ref string
pathID int64
}
grouped := map[string]gt{}
for _, h := range hits {
Expand All @@ -29,12 +30,13 @@ func updateCampaignStats(ctx context.Context, hits []goatcounter.Hit) error {
}

day := h.CreatedAt.Format("2006-01-02")
k := day + strconv.FormatInt(*h.CampaignID, 10) + h.Ref
k := day + strconv.FormatInt(*h.CampaignID, 10) + h.Ref + strconv.FormatInt(h.PathID, 10)
v := grouped[k]
if v.count == 0 {
v.day = day
v.campaignID = *h.CampaignID
v.ref = h.Ref
v.pathID = h.PathID
}

v.count += 1
Expand All @@ -46,9 +48,9 @@ func updateCampaignStats(ctx context.Context, hits []goatcounter.Hit) error {

siteID := goatcounter.MustGetSite(ctx).ID
ins := zdb.NewBulkInsert(ctx, "campaign_stats", []string{"site_id", "day",
"campaign_id", "ref", "count", "count_unique"})
"path_id", "campaign_id", "ref", "count", "count_unique"})
if zdb.SQLDialect(ctx) == zdb.DialectPostgreSQL {
ins.OnConflict(`on conflict on constraint "campaign_stats#site_id#campaign_id#ref#day" do update set
ins.OnConflict(`on conflict on constraint "campaign_stats#site_id#path_id#campaign_id#ref#day" do update set
count = campaign_stats.count + excluded.count,
count_unique = campaign_stats.count_unique + excluded.count_unique`)

Expand All @@ -57,13 +59,13 @@ func updateCampaignStats(ctx context.Context, hits []goatcounter.Hit) error {
return err
}
} else {
ins.OnConflict(`on conflict(site_id, campaign_id, ref, day) do update set
ins.OnConflict(`on conflict(site_id, path_id, campaign_id, ref, day) do update set
count = campaign_stats.count + excluded.count,
count_unique = campaign_stats.count_unique + excluded.count_unique`)
}

for _, v := range grouped {
ins.Values(siteID, v.day, v.campaignID, v.ref, v.count, v.countUnique)
ins.Values(siteID, v.day, v.pathID, v.campaignID, v.ref, v.count, v.countUnique)
}
return ins.Finish()
}), "cron.updateCampaignStats")
Expand Down
17 changes: 17 additions & 0 deletions db/migrate/2022-10-17-1-campaigns.gotxt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
drop table campaign_stats; -- Wasn't correct before, so just drop it.

create table campaign_stats (
site_id integer not null,
path_id integer not null,

day date not null,
campaign_id integer not null,
ref varchar not null,
count integer not null,
count_unique integer not null,

constraint "campaign_stats#site_id#path_id#campaign_id#ref#day" unique(site_id, path_id, campaign_id, ref, day) {{sqlite "on conflict replace"}}
);
create index "campaign_stats#site_id#day" on campaign_stats(site_id, day desc);
{{cluster "campaign_stats" "campaign_stats#site_id#day"}}
{{replica "campaign_stats" "campaign_stats#site_id#path_id#campaign_id#ref#day"}}
28 changes: 18 additions & 10 deletions hit.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,20 +195,27 @@ func (h *Hit) Defaults(ctx context.Context, initial bool) error {
}
q := u.Query()

for _, c := range site.Settings.Campaigns {
if c == "utm_campaign" { // Ignore as we track this as the campaign name.
// Get referral from query
for _, c := range []string{"utm_source", "ref", "src", "source"} {
v := strings.TrimSpace(q.Get(c))
if v == "" {
continue
}
if _, ok := q[c]; ok {
h.Ref = q.Get(c)
h.RefURL = nil
h.RefScheme = RefSchemeCampaign
break
}

h.Ref = v
h.RefURL = nil
h.RefScheme = RefSchemeOther
break
}

if q.Has("utm_campaign") {
c := Campaign{Name: q.Get("utm_campaign")}
// Get campaign.
for _, c := range []string{"utm_campaign", "campaign"} {
v := strings.TrimSpace(q.Get(c))
if v == "" {
continue
}

c := Campaign{Name: v}
err := c.ByName(ctx, c.Name)
if err != nil && !zdb.ErrNoRows(err) {
return errors.Wrap(err, "Hit.Defaults")
Expand All @@ -221,6 +228,7 @@ func (h *Hit) Defaults(ctx context.Context, initial bool) error {
}
}
h.CampaignID = &c.ID
h.RefScheme = RefSchemeCampaign
}
}

Expand Down
5 changes: 1 addition & 4 deletions settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ type (
AllowCounter bool `json:"allow_counter"`
AllowBosmang bool `json:"allow_bosmang"`
DataRetention int `json:"data_retention"`
Campaigns Strings `json:"campaigns"`
Campaigns Strings `json:"-"`
IgnoreIPs Strings `json:"ignore_ips"`
Collect zint.Bitflag16 `json:"collect"`
CollectRegions Strings `json:"collect_regions"`
Expand Down Expand Up @@ -337,9 +337,6 @@ func (w *Widgets) UnmarshalJSON(d []byte) error {
}

func (ss *SiteSettings) Defaults(ctx context.Context) {
if ss.Campaigns == nil {
ss.Campaigns = []string{"utm_source", "ref", "src", "source"}
}
if ss.Public == "" {
ss.Public = "private"
}
Expand Down
1 change: 1 addition & 0 deletions tpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ func init() {
{href: "modify", label: "Change data before it's sent to GoatCounter?"},
{href: "domains", label: "Track multiple domains/sites?"},
{href: "spa", label: "Add GoatCounter to a SPA?"},
{href: "campaigns", label: "Track campaigns?"},
{href: "beacon", label: "Use navigator.sendBeacon?"},
{href: "countjs-versions", label: "count.js versions and SRI"},
{href: "countjs-host", label: "Host count.js somewhere else?"},
Expand Down
10 changes: 10 additions & 0 deletions tpl/help/campaigns.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Campaigns are tracked automatically based on URL query parameters:

- The campaign name is in the `utm_campaign` or `campaign` parameter.

- An optional source can be in the `utm_source`, `ref`, `src`, or `source`
parameter (it will use the Referrer if this is missing).

There is no need to "create" campaigns; once it sees a campaign with a new name
it will be created automatically and shown in the Campaigns dashboard widget.

6 changes: 0 additions & 6 deletions tpl/settings_main.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,6 @@
(tag "a" (printf `target="_blank" href="%s#toggle-goatcounter"` (.Site.LinkDomainURL true)))}}
{{end}}
</span>

<label>{{.T "label/campaign-parameters|Referral parameters"}}</label>
<input type="text" name="settings.campaigns" value="{{.Site.Settings.Campaigns}}">
{{validate "site.settings.campaigns" .Validate}}
<span>{{.T `help/campaign-parameters|List of parameters to use as the ‘referal’; will use the Referal HTTP header if none are set.`}}
</span>
</fieldset>

<fieldset id="section-collect">
Expand Down

0 comments on commit fff99bc

Please sign in to comment.