@@ -99,87 +99,112 @@ if ('issueNumber' in options && typeof options.issueNumber === 'number') {
99
99
}
100
100
}
101
101
102
+ const getUrlWithUtmTrackingParams = ( { url, medium = 'newsletter' } ) => {
103
+ const utmParams = {
104
+ utm_source : 'scriptified.dev' ,
105
+ utm_medium : medium ,
106
+ } ;
107
+
108
+ try {
109
+ const urlWithParams = new URL ( url ) ;
110
+
111
+ Object . keys ( utmParams ) . forEach ( key => {
112
+ urlWithParams . searchParams . set ( key , utmParams [ key ] ) ;
113
+ } ) ;
114
+
115
+ return urlWithParams . toString ( ) ;
116
+ } catch ( err ) {
117
+ console . error ( err ) ;
118
+ // return url as is if URL is invalid
119
+ return url ;
120
+ }
121
+ } ;
122
+
102
123
const ogImgURL = getOGImage ( currentIssue . title , currentIssue . id , currentIssue . date ) ;
103
124
125
+ const issueWebUrl = getUrlWithUtmTrackingParams ( { url : `https://scriptified.dev/issues/${ currentIssue . id } ` } ) ;
126
+
104
127
const emailTemplate = `
105
128

106
129
107
- <center>[Read issue on web](https://scriptified.dev/issues/ ${ currentIssue . id } )</center>
130
+ <center>[Read issue on web](${ issueWebUrl } )</center>
108
131
109
132
${ currentIssue . description }
110
133
111
134
# Tip of the day
112
135
113
136
${ currentIssue . tip_of_the_week . description }
114
137
115
- ${ currentIssue . tip_of_the_week . codeSnippet &&
116
- `
138
+ ${
139
+ currentIssue . tip_of_the_week . codeSnippet &&
140
+ `
117
141
\`\`\`${ currentIssue . tip_of_the_week . codeSnippet . language }
118
142
${ currentIssue . tip_of_the_week . codeSnippet . code . code }
119
143
\`\`\`
120
144
`
121
- }
145
+ }
122
146
123
147
${ getAuthors ( currentIssue . tip_of_the_week ?. authors ) }
124
148
___
125
149
126
150
# Articles
127
151
128
152
${ currentIssue . articles
129
- . map (
130
- article =>
131
- `[**${ article . title } **](${ article . url } )
153
+ . map (
154
+ article =>
155
+ `[**${ article . title } **](${ getUrlWithUtmTrackingParams ( { url : article . url } ) } )
132
156
133
157
${ article . description }
134
158
135
159
${ getAuthors ( article ?. authors ) }
136
160
`
137
- )
138
- . join ( '\n' ) }
161
+ )
162
+ . join ( '\n' ) }
139
163
140
164
___
141
165
142
- ${ currentIssue . devOfTheWeek
143
- ? `# Dev of the Week
166
+ ${
167
+ currentIssue . devOfTheWeek
168
+ ? `# Dev of the Week
144
169
145
170
<img alt="${ currentIssue . devOfTheWeek . name } " src="${ getAssetURL (
146
- currentIssue . id ,
147
- currentIssue . devOfTheWeek . profileImg
148
- ) } " style="width:200px;"/>
171
+ currentIssue . id ,
172
+ currentIssue . devOfTheWeek . profileImg
173
+ ) } " style="width:200px;"/>
149
174
150
175
## ${ currentIssue . devOfTheWeek . name }
151
176
${ currentIssue . devOfTheWeek . bio }
152
177
153
178
${ Object . keys ( currentIssue . devOfTheWeek )
154
- . filter ( key => PROFILE_KEYS . includes ( key ) && currentIssue . devOfTheWeek [ key ] !== null )
155
- . map ( profile => `[${ PROFILE_TYPES [ profile ] } ](${ currentIssue . devOfTheWeek [ profile ] } )` )
156
- . join ( ' | ' ) }
179
+ . filter ( key => PROFILE_KEYS . includes ( key ) && currentIssue . devOfTheWeek [ key ] !== null )
180
+ . map ( profile => `[${ PROFILE_TYPES [ profile ] } ](${ currentIssue . devOfTheWeek [ profile ] } )` )
181
+ . join ( ' | ' ) }
157
182
158
183
___`
159
- : ''
160
- }
184
+ : ''
185
+ }
161
186
162
187
# Tools
163
188
164
189
${ currentIssue . tools
165
- . map (
166
- tool =>
167
- `[**${ tool . name } **](${ tool . url } )
190
+ . map (
191
+ tool =>
192
+ `[**${ tool . name } **](${ getUrlWithUtmTrackingParams ( { url : tool . url } ) } )
168
193
169
194
${ tool . description }
170
195
171
196
${ getAuthors ( tool ?. authors ) }
172
197
`
173
- )
174
- . join ( '\n' ) }
198
+ )
199
+ . join ( '\n' ) }
175
200
176
201
___
177
202
178
203
# Tech Talks
179
204
180
- [**${ currentIssue . talks [ 0 ] . title } **](${ currentIssue . talks [ 0 ] . url } )
205
+ [**${ currentIssue . talks [ 0 ] . title } **](${ getUrlWithUtmTrackingParams ( { url : currentIssue . talks [ 0 ] . url } ) } )
181
206
182
- ${ currentIssue . talks [ 0 ] . url }
207
+ ${ getUrlWithUtmTrackingParams ( { url : currentIssue . talks [ 0 ] . url } ) } )
183
208
184
209
${ currentIssue . talks [ 0 ] . description }
185
210
195
220
${ currentIssue . quiz . codeSnippet . code . code }
196
221
\`\`\`
197
222
198
- ${ currentIssue . quiz . options . map (
199
- option => `[<div style="margin: 12px 0px; border: 1px solid gray; padding: 16px; background: #F2F3F5;">${ option . text . split ( '\n' ) . join ( '<br>' ) } </div>](https://scriptified.dev/issues/${ currentIssue . id } ?section=quiz&option=${ option . option_id } )`
200
- ) . join ( '\n' ) }
223
+ ${ currentIssue . quiz . options
224
+ . map (
225
+ option =>
226
+ `[<div style="margin: 12px 0px; border: 1px solid gray; padding: 16px; background: #F2F3F5;">${ option . text
227
+ . split ( '\n' )
228
+ . join ( '<br>' ) } </div>](https://scriptified.dev/issues/${ currentIssue . id } ?section=quiz&option=${
229
+ option . option_id
230
+ } )`
231
+ )
232
+ . join ( '\n' ) }
201
233
202
234
203
235
___
213
245
Liked this issue? [Share on Twitter](https://twitter.com/intent/tweet?text=${ encodeURIComponent ( `Have a look at issue #${ currentIssue . id } of Scriptified.
214
246
215
247
Subscribe to @scriptified_dev for more.` ) } &url=${ encodeURIComponent (
216
- `https://scriptified.dev/issues/ ${ currentIssue . id } `
217
- ) } ) or [read previous issues](https://scriptified.dev/issues).
248
+ ` ${ issueWebUrl } `
249
+ ) } ) or [read previous issues](https://scriptified.dev/issues).
218
250
` ;
219
251
const archiveDirectory = './archives' ;
220
252
const issueFile = `${ archiveDirectory } /issue${ currentIssue . id } .md` ;
0 commit comments