You are simply missing a few single quotes around your date variables. Since you are building your query in dynamic SQL, your dates are passed into the dynamic query as date literals, so therefore they need single quotes around them.
To represent a single quote in your dynamic SQL, you actually need 3 single quotes, as you already have around your @ID variable. At the end, you need 4 single quotes to both add the single quote into the dynamic and also to terminate the EXEC string.
So it would look like this:
DECLARE @periodEnd datetime = '2021-12-09 02:41:42.000'
DECLARE @ID VARCHAR(50) = '35915D4B-E210-48C0-ADD5-C68AAEB62C36'
EXEC('SELECT COUNT(*) AS count FROM pageloads nolock WHERE domainId = ''' + @ID+ ''' AND paid = 1 AND source IN (2) AND clickedOn BETWEEN DATEADD(MONTH, -3,''' + @periodEnd + ''') AND ''' + @periodEnd + '''')
Any time I pass variables into Dynamic SQL I always end up with code littered with single quotes like this.
It looks like you are trying to use the WITH(NOLOCK) table hint to speed up the process and to prevent any performance impact while you're running this count, which is a good idea. You will get a lot of pushback on this website about using WITH(NOLOCK), but not from me. It's a very useful feature for this type of query, where you want a quick number and don't want to grind your logging process to a halt while you get it.
The correct syntax to use WITH(NOLOCK) would be:
DECLARE @periodEnd datetime = '2021-12-09 02:41:42.000'
DECLARE @ID VARCHAR(50) = '35915D4B-E210-48C0-ADD5-C68AAEB62C36'
EXEC('SELECT COUNT(*) AS count FROM pageloads pl WITH(NOLOCK) WHERE domainId = ''' + @ID+ ''' AND paid = 1 AND source IN (2) AND clickedOn BETWEEN DATEADD(MONTH, -3,''' + @periodEnd + ''') AND ''' + @periodEnd + '''')
Previously you were using "nolock" as a table alias, which is not a great idea. I changed the table alias to "pl".