collect jobSource when manual startup chat running; add jobSource in gtag both auto or manual

This commit is contained in:
geekgeekrun
2025-07-13 18:40:59 +08:00
parent e867acb39d
commit 7b10e97fa8
4 changed files with 85 additions and 23 deletions

View File

@@ -1,3 +1,7 @@
export const activeDescList = [
'', "半年前活跃","近半年活跃","5月内活跃","4月内活跃","3月内活跃","2月内活跃","本月活跃","2周内活跃","本周活跃","3日内活跃","昨日活跃","今日活跃","刚刚活跃"
]
]
export const RECOMMEND_JOB_ENTRY_SELECTOR = `.c-expect-select a[ka="jobs_recommend_tab_click"]`
export const USER_SET_EXPECT_JOB_ENTRIES_SELECTOR = `.c-expect-select .expect-list .expect-item`
export const SEARCH_BOX_SELECTOR = `.c-search-input .search-input-box`

View File

@@ -21,7 +21,12 @@ import { default as jobFilterConditions } from './internal-config/job-filter-con
import { default as rawIndustryFilterExemption } from './internal-config/job-filter-industry-filter-exemption-20241002.json'
import { ChatStartupFrom } from '@geekgeekrun/sqlite-plugin/dist/entity/ChatStartupLog'
import { MarkAsNotSuitReason, MarkAsNotSuitOp, StrategyScopeOptionWhenMarkJobNotMatch, SalaryCalculateWay, JobDetailRegExpMatchLogic, JobSource } from '@geekgeekrun/sqlite-plugin/dist/enums'
import { activeDescList } from './constant.mjs'
import {
activeDescList,
RECOMMEND_JOB_ENTRY_SELECTOR,
USER_SET_EXPECT_JOB_ENTRIES_SELECTOR,
SEARCH_BOX_SELECTOR,
} from './constant.mjs'
import { parseSalary } from "@geekgeekrun/sqlite-plugin/dist/utils/parser"
const jobFilterConditionsMapByCode = {}
Object.values(jobFilterConditions).forEach(arr => {
@@ -534,10 +539,6 @@ async function toRecommendPage (hooks) {
}
}
const RECOMMEND_JOB_ENTRY_SELECTOR = `.c-expect-select a[ka="jobs_recommend_tab_click"]`
const USER_SET_EXPECT_JOB_ENTRIES_SELECTOR = `.c-expect-select .expect-list .expect-item`
const SEARCH_BOX_SELECTOR = `.c-search-input .search-input-box`
const computedSourceList = []
for (const source of normalizedJobSource) {
switch (source.type) {

View File

@@ -4,6 +4,10 @@ import {
readStorageFile,
writeStorageFile
} from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
import {
RECOMMEND_JOB_ENTRY_SELECTOR,
USER_SET_EXPECT_JOB_ENTRIES_SELECTOR,
} from '@geekgeekrun/geek-auto-start-chat-with-boss/constant.mjs'
import { setDomainLocalStorage } from '@geekgeekrun/utils/puppeteer/local-storage.mjs'
import {
saveJobInfoFromRecommendPage,
@@ -13,7 +17,7 @@ import {
} from '@geekgeekrun/sqlite-plugin/dist/handlers'
import { initDb } from '@geekgeekrun/sqlite-plugin'
import { getPublicDbFilePath } from '@geekgeekrun/geek-auto-start-chat-with-boss/runtime-file-utils.mjs'
import { MarkAsNotSuitReason } from '@geekgeekrun/sqlite-plugin/dist/enums'
import { MarkAsNotSuitReason, JobSource } from '@geekgeekrun/sqlite-plugin/dist/enums'
import fs from 'node:fs'
import { Target } from 'puppeteer'
@@ -38,6 +42,49 @@ const attachRequestsListener = async (target: Target) => {
if (!page) {
return
}
async function getCurrentJobSource() {
const methodMap = {
async recommend() {
return await page.evaluate(
({ RECOMMEND_JOB_ENTRY_SELECTOR }) => {
return document.querySelector(RECOMMEND_JOB_ENTRY_SELECTOR).classList.contains('active')
},
{
RECOMMEND_JOB_ENTRY_SELECTOR
}
)
},
async expect() {
return await page.evaluate(
({ USER_SET_EXPECT_JOB_ENTRIES_SELECTOR }) => {
return [...document.querySelectorAll(USER_SET_EXPECT_JOB_ENTRIES_SELECTOR)].some((el) =>
el.classList.contains('active')
)
},
{
USER_SET_EXPECT_JOB_ENTRIES_SELECTOR
}
)
},
async search() {
const elHandle = await page.$(`.page-jobs-main`)
const currentKeyWord = await elHandle?.evaluate((el) => {
return el?.__vue__?.formData?.query
})
return !!currentKeyWord
}
}
for (const [type, func] of Object.entries(methodMap)) {
try {
if (await func()) {
return type
}
} catch (err) {
console.error('encounter error when get job source')
}
}
return null
}
page.on('response', async (response) => {
if (response.url().startsWith('https://www.zhipin.com/wapi/zpgeek/job/detail.json')) {
@@ -81,7 +128,7 @@ const attachRequestsListener = async (target: Target) => {
const reasonCodeToTextMap = await readStorageFile(
'job-not-suit-reason-code-to-text-cache.json'
)
const jobSource = await getCurrentJobSource()
const markDetail = {
markFrom: ChatStartupFrom.ManuallyFromRecommendList,
extInfo: {
@@ -90,12 +137,14 @@ const attachRequestsListener = async (target: Target) => {
text: reasonCodeToTextMap[chosenCode]
}
},
markReason: MarkAsNotSuitReason.USER_MANUAL_OPERATION_WITH_UNKNOWN_REASON
markReason: MarkAsNotSuitReason.USER_MANUAL_OPERATION_WITH_UNKNOWN_REASON,
jobSource: JobSource[jobSource]
}
gtag('job_marked_as_not_suit', {
markFrom: markDetail.markFrom,
bossActiveTimeDesc: currentJobData?.bossInfo?.activeTimeDesc,
encryptJobId: currentJobData?.jobInfo?.encryptId
encryptJobId: currentJobData?.jobInfo?.encryptId,
jobSource: JobSource[jobSource]
})
if (reasonCodeToTextMap[chosenCode]?.includes('活跃度低')) {
markDetail.markReason = MarkAsNotSuitReason.BOSS_INACTIVE
@@ -131,9 +180,11 @@ const attachRequestsListener = async (target: Target) => {
const currentUserInfo = await page.evaluate(
'document.querySelector(".job-detail-box").__vue__.$store.state.userInfo'
)
const jobSource = await getCurrentJobSource()
gtag('new_chat_startup', {
chatStartupFrom: ChatStartupFrom.ManuallyFromRecommendList,
encryptJobId: currentJobData?.jobInfo?.encryptId
encryptJobId: currentJobData?.jobInfo?.encryptId,
jobSource: JobSource[jobSource]
})
await saveChatStartupRecord(
await dbInitPromise,
@@ -142,7 +193,8 @@ const attachRequestsListener = async (target: Target) => {
encryptUserId: currentUserInfo.encryptUserId
},
{
chatStartupFrom: ChatStartupFrom.ManuallyFromRecommendList
chatStartupFrom: ChatStartupFrom.ManuallyFromRecommendList,
jobSource: JobSource[jobSource]
}
)
} else if (

View File

@@ -2,21 +2,26 @@ import gtag from '.'
export default class GtagPlugin {
apply(hooks) {
hooks.newChatStartup.tap('GtagPlugin', (jobData, { chatStartupFrom }) => {
hooks.newChatStartup.tap('GtagPlugin', (jobData, { chatStartupFrom, jobSource }) => {
gtag('new_chat_startup', {
chatStartupFrom,
encryptJobId: jobData.jobInfo.encryptId
})
})
hooks.jobMarkedAsNotSuit.tap('GtagPlugin', (jobData, { markFrom, markOp, markReason }) => {
gtag('job_marked_as_not_suit', {
markFrom,
markOp,
markReason,
bossActiveTimeDesc: jobData.bossInfo.activeTimeDesc,
encryptJobId: jobData.jobInfo.encryptId
encryptJobId: jobData.jobInfo.encryptId,
jobSource
})
})
hooks.jobMarkedAsNotSuit.tap(
'GtagPlugin',
(jobData, { markFrom, markOp, markReason, jobSource }) => {
gtag('job_marked_as_not_suit', {
markFrom,
markOp,
markReason,
bossActiveTimeDesc: jobData.bossInfo.activeTimeDesc,
encryptJobId: jobData.jobInfo.encryptId,
jobSource
})
}
)
hooks.noPositionFoundForCurrentJob.tap('GtagPlugin', () => {
gtag('no_position_found_for_current_job')
})