mirror of
https://github.com/knadh/listmonk.git
synced 2025-10-10 23:40:55 +08:00
Fix incorrect analytics count. Closes #712.
This commit is contained in:
parent
fb3c429116
commit
3550d5453d
3 changed files with 43 additions and 30 deletions
24
cmd/init.go
24
cmd/init.go
|
@ -283,19 +283,25 @@ func readQueries(sqlFile string, db *sqlx.DB, fs stuffbin.FileSystem) goyesql.Qu
|
||||||
|
|
||||||
// prepareQueries queries prepares a query map and returns a *Queries
|
// prepareQueries queries prepares a query map and returns a *Queries
|
||||||
func prepareQueries(qMap goyesql.Queries, db *sqlx.DB, ko *koanf.Koanf) *models.Queries {
|
func prepareQueries(qMap goyesql.Queries, db *sqlx.DB, ko *koanf.Koanf) *models.Queries {
|
||||||
// The campaign view/click count queries have a COUNT(%s) placeholder that should either
|
var (
|
||||||
// be substituted with * to pull non-unique rows when individual subscriber tracking is off
|
countQuery = "get-campaign-analytics-counts"
|
||||||
// as all subscriber_ids will be null, or with DISTINCT subscriber_id when tracking is on
|
linkSel = "*"
|
||||||
// to only pull unique rows per subscriber.
|
)
|
||||||
sel := "*"
|
|
||||||
if ko.Bool("privacy.individual_tracking") {
|
if ko.Bool("privacy.individual_tracking") {
|
||||||
sel = "DISTINCT subscriber_id"
|
countQuery = "get-campaign-analytics-unique-counts"
|
||||||
|
linkSel = "DISTINCT subscriber_id"
|
||||||
}
|
}
|
||||||
|
|
||||||
keys := []string{"get-campaign-view-counts", "get-campaign-click-counts", "get-campaign-link-counts"}
|
// These don't exist in the SQL file but are in the queries struct to be prepared.
|
||||||
for _, k := range keys {
|
qMap["get-campaign-view-counts"] = &goyesql.Query{
|
||||||
qMap[k].Query = fmt.Sprintf(qMap[k].Query, sel)
|
Query: fmt.Sprintf(qMap[countQuery].Query, "campaign_views"),
|
||||||
|
Tags: map[string]string{"name": "get-campaign-view-counts"},
|
||||||
}
|
}
|
||||||
|
qMap["get-campaign-click-counts"] = &goyesql.Query{
|
||||||
|
Query: fmt.Sprintf(qMap[countQuery].Query, "link_clicks"),
|
||||||
|
Tags: map[string]string{"name": "get-campaign-click-counts"},
|
||||||
|
}
|
||||||
|
qMap["get-campaign-link-counts"].Query = fmt.Sprintf(qMap["get-campaign-link-counts"].Query, linkSel)
|
||||||
|
|
||||||
// Scan and prepare all queries.
|
// Scan and prepare all queries.
|
||||||
var q models.Queries
|
var q models.Queries
|
||||||
|
|
|
@ -56,10 +56,16 @@ type Queries struct {
|
||||||
GetCampaignForPreview *sqlx.Stmt `query:"get-campaign-for-preview"`
|
GetCampaignForPreview *sqlx.Stmt `query:"get-campaign-for-preview"`
|
||||||
GetCampaignStats *sqlx.Stmt `query:"get-campaign-stats"`
|
GetCampaignStats *sqlx.Stmt `query:"get-campaign-stats"`
|
||||||
GetCampaignStatus *sqlx.Stmt `query:"get-campaign-status"`
|
GetCampaignStatus *sqlx.Stmt `query:"get-campaign-status"`
|
||||||
|
|
||||||
|
// These two queries are read as strings and based on settings.individual_tracking=on/off,
|
||||||
|
// are interpolated and copied to view and click counts. Same query, different tables.
|
||||||
|
GetCampaignAnalyticsCounts string `query:"get-campaign-analytics-counts"`
|
||||||
|
GetCampaignAnalyticsCountsUnique string `query:"get-campaign-analytics-unique-counts"`
|
||||||
GetCampaignViewCounts *sqlx.Stmt `query:"get-campaign-view-counts"`
|
GetCampaignViewCounts *sqlx.Stmt `query:"get-campaign-view-counts"`
|
||||||
GetCampaignClickCounts *sqlx.Stmt `query:"get-campaign-click-counts"`
|
GetCampaignClickCounts *sqlx.Stmt `query:"get-campaign-click-counts"`
|
||||||
GetCampaignLinkCounts *sqlx.Stmt `query:"get-campaign-link-counts"`
|
GetCampaignLinkCounts *sqlx.Stmt `query:"get-campaign-link-counts"`
|
||||||
GetCampaignBounceCounts *sqlx.Stmt `query:"get-campaign-bounce-counts"`
|
GetCampaignBounceCounts *sqlx.Stmt `query:"get-campaign-bounce-counts"`
|
||||||
|
|
||||||
NextCampaigns *sqlx.Stmt `query:"next-campaigns"`
|
NextCampaigns *sqlx.Stmt `query:"next-campaigns"`
|
||||||
NextCampaignSubscribers *sqlx.Stmt `query:"next-campaign-subscribers"`
|
NextCampaignSubscribers *sqlx.Stmt `query:"next-campaign-subscribers"`
|
||||||
GetOneCampaignSubscriber *sqlx.Stmt `query:"get-one-campaign-subscriber"`
|
GetOneCampaignSubscriber *sqlx.Stmt `query:"get-one-campaign-subscriber"`
|
||||||
|
|
23
queries.sql
23
queries.sql
|
@ -569,27 +569,28 @@ u AS (
|
||||||
)
|
)
|
||||||
SELECT * FROM camps;
|
SELECT * FROM camps;
|
||||||
|
|
||||||
-- name: get-campaign-view-counts
|
-- name: get-campaign-analytics-unique-counts
|
||||||
-- raw: true
|
|
||||||
-- %s = * or DISTINCT subscriber_id (prepared based on based on individual tracking=on/off). Prepared on boot.
|
|
||||||
WITH intval AS (
|
WITH intval AS (
|
||||||
-- For intervals < a week, aggregate counts hourly, otherwise daily.
|
-- For intervals < a week, aggregate counts hourly, otherwise daily.
|
||||||
SELECT CASE WHEN (EXTRACT (EPOCH FROM ($3::TIMESTAMP - $2::TIMESTAMP)) / 86400) >= 7 THEN 'day' ELSE 'hour' END
|
SELECT CASE WHEN (EXTRACT (EPOCH FROM ($3::TIMESTAMP - $2::TIMESTAMP)) / 86400) >= 7 THEN 'day' ELSE 'hour' END
|
||||||
)
|
),
|
||||||
SELECT campaign_id, COUNT(%s) AS "count", DATE_TRUNC((SELECT * FROM intval), created_at) AS "timestamp"
|
uniqIDs AS (
|
||||||
FROM campaign_views
|
SELECT DISTINCT ON(subscriber_id) subscriber_id, campaign_id, DATE_TRUNC((SELECT * FROM intval), created_at) AS "timestamp"
|
||||||
|
FROM %s
|
||||||
WHERE campaign_id=ANY($1) AND created_at >= $2 AND created_at <= $3
|
WHERE campaign_id=ANY($1) AND created_at >= $2 AND created_at <= $3
|
||||||
GROUP BY campaign_id, "timestamp" ORDER BY "timestamp" ASC;
|
ORDER BY subscriber_id, "timestamp"
|
||||||
|
)
|
||||||
|
SELECT COUNT(*) AS "count", campaign_id, "timestamp"
|
||||||
|
FROM uniqIDs GROUP BY campaign_id, "timestamp";
|
||||||
|
|
||||||
-- name: get-campaign-click-counts
|
-- name: get-campaign-analytics-counts
|
||||||
-- raw: true
|
-- raw: true
|
||||||
-- %s = * or DISTINCT subscriber_id (prepared based on based on individual tracking=on/off). Prepared on boot.
|
|
||||||
WITH intval AS (
|
WITH intval AS (
|
||||||
-- For intervals < a week, aggregate counts hourly, otherwise daily.
|
-- For intervals < a week, aggregate counts hourly, otherwise daily.
|
||||||
SELECT CASE WHEN (EXTRACT (EPOCH FROM ($3::TIMESTAMP - $2::TIMESTAMP)) / 86400) >= 7 THEN 'day' ELSE 'hour' END
|
SELECT CASE WHEN (EXTRACT (EPOCH FROM ($3::TIMESTAMP - $2::TIMESTAMP)) / 86400) >= 7 THEN 'day' ELSE 'hour' END
|
||||||
)
|
)
|
||||||
SELECT campaign_id, COUNT(%s) AS "count", DATE_TRUNC((SELECT * FROM intval), created_at) AS "timestamp"
|
SELECT campaign_id, COUNT(*) AS "count", DATE_TRUNC((SELECT * FROM intval), created_at) AS "timestamp"
|
||||||
FROM link_clicks
|
FROM %s
|
||||||
WHERE campaign_id=ANY($1) AND created_at >= $2 AND created_at <= $3
|
WHERE campaign_id=ANY($1) AND created_at >= $2 AND created_at <= $3
|
||||||
GROUP BY campaign_id, "timestamp" ORDER BY "timestamp" ASC;
|
GROUP BY campaign_id, "timestamp" ORDER BY "timestamp" ASC;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue