diff --git a/services/web/app/src/Features/LinkedFiles/LinkedFilesController.js b/services/web/app/src/Features/LinkedFiles/LinkedFilesController.js
index eff0e9513b..e809c02bec 100644
--- a/services/web/app/src/Features/LinkedFiles/LinkedFilesController.js
+++ b/services/web/app/src/Features/LinkedFiles/LinkedFilesController.js
@@ -18,7 +18,9 @@ const ProjectLocator = require('../Project/ProjectLocator')
const Settings = require('@overleaf/settings')
const logger = require('@overleaf/logger')
const _ = require('lodash')
+const AnalyticsManager = require('../../../../app/src/Features/Analytics/AnalyticsManager')
const LinkedFilesHandler = require('./LinkedFilesHandler')
+
const {
CompileFailedError,
UrlFetchFailedError,
@@ -91,6 +93,11 @@ module.exports = LinkedFilesController = {
if (err != null) {
return LinkedFilesController.handleError(err, req, res, next)
}
+ if (name.endsWith('.bib')) {
+ AnalyticsManager.recordEventForUser(userId, 'linked-bib-file', {
+ integration: provider,
+ })
+ }
return res.json({ new_file_id: newFileId })
}
)
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-create-new-doc.jsx b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-create-new-doc.jsx
index 9e60cb467e..2f72234c0a 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-create-new-doc.jsx
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-create-new-doc.jsx
@@ -22,7 +22,10 @@ export default function FileTreeCreateNewDoc() {
event.preventDefault()
finishCreatingDoc({ name })
- eventTracking.sendMB('new-file-created', { method: 'doc' })
+ eventTracking.sendMB('new-file-created', {
+ method: 'doc',
+ extension: name.split('.').length > 1 ? name.split('.').pop() : '',
+ })
},
[finishCreatingDoc, name]
)
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.tsx b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.tsx
index 9380084a4a..c8f181ab9c 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.tsx
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-project.tsx
@@ -95,7 +95,10 @@ export default function FileTreeImportFromProject() {
// form submission: create a linked file with this name, from this entity or output file
const handleSubmit: FormEventHandler = event => {
event.preventDefault()
- eventTracking.sendMB('new-file-created', { method: 'project' })
+ eventTracking.sendMB('new-file-created', {
+ method: 'project',
+ extension: name.split('.').length > 1 ? name.split('.').pop() : '',
+ })
if (isOutputFilesMode) {
finishCreatingLinkedFile({
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.jsx b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.jsx
index 13d006aa00..23aac7d7e1 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.jsx
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-import-from-url.jsx
@@ -36,7 +36,10 @@ export default function FileTreeImportFromUrl() {
// form submission: create a linked file with this name, from this URL
const handleSubmit = event => {
event.preventDefault()
- eventTracking.sendMB('new-file-created', { method: 'url' })
+ eventTracking.sendMB('new-file-created', {
+ method: 'url',
+ extension: name.split('.').length > 1 ? name.split('.').pop() : '',
+ })
finishCreatingLinkedFile({
name,
provider: 'url',
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.tsx b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.tsx
index ec04578ebe..ccf7428101 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.tsx
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-create/modes/file-tree-upload-doc.tsx
@@ -145,7 +145,13 @@ export default function FileTreeUploadDoc() {
})
// broadcast doc metadata after each successful upload
.on('upload-success', (file, response) => {
- eventTracking.sendMB('new-file-created', { method: 'upload' })
+ eventTracking.sendMB('new-file-created', {
+ method: 'upload',
+ extension:
+ file?.name && file?.name.split('.').length > 1
+ ? file?.name.split('.').pop()
+ : '',
+ })
if (response.body.entity_type === 'doc') {
window.setTimeout(() => {
refreshProjectMetadata(projectId, response.body.entity_id)
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-menu-items.jsx b/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-menu-items.jsx
index 05608fe488..85431aa5ef 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-menu-items.jsx
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-menu-items.jsx
@@ -1,12 +1,30 @@
+import { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import * as eventTracking from '../../../../infrastructure/event-tracking'
+import { useProjectContext } from '@/shared/context/project-context'
import { MenuItem } from 'react-bootstrap'
import { useFileTreeActionable } from '../../contexts/file-tree-actionable'
+import { useFileTreeData } from '@/shared/context/file-tree-data-context'
+import { useFileTreeSelectable } from '../../contexts/file-tree-selectable'
+import { findInTree } from '../../util/find-in-tree'
function FileTreeItemMenuItems() {
const { t } = useTranslation()
+ const { fileTreeData } = useFileTreeData()
+ const { selectedEntityIds } = useFileTreeSelectable()
+
+ // return the name of the selected file or doc if there is only one selected
+ const selectedFileName = useMemo(() => {
+ if (selectedEntityIds.size === 1) {
+ const [selectedEntityId] = selectedEntityIds
+ const selectedEntity = findInTree(fileTreeData, selectedEntityId)
+ return selectedEntity?.entity?.name
+ }
+ return null
+ }, [fileTreeData, selectedEntityIds])
+
const {
canRename,
canDelete,
@@ -19,15 +37,24 @@ function FileTreeItemMenuItems() {
downloadPath,
} = useFileTreeActionable()
- const createWithAnalytics = () => {
+ const { owner } = useProjectContext()
+
+ const downloadWithAnalytics = useCallback(() => {
+ // we are only interested in downloads of bib files WRT analytics, for the purposes of promoting the tpr integrations
+ if (selectedFileName?.endsWith('.bib')) {
+ eventTracking.sendMB('download-bib-file', { projectOwner: owner._id })
+ }
+ }, [selectedFileName, owner])
+
+ const createWithAnalytics = useCallback(() => {
eventTracking.sendMB('new-file-click', { location: 'file-menu' })
startCreatingDocOrFile()
- }
+ }, [startCreatingDocOrFile])
- const uploadWithAnalytics = () => {
+ const uploadWithAnalytics = useCallback(() => {
eventTracking.sendMB('upload-click', { location: 'file-menu' })
startUploadingDocOrFile()
- }
+ }, [startUploadingDocOrFile])
return (
<>
@@ -35,7 +62,7 @@ function FileTreeItemMenuItems() {
) : null}
{downloadPath ? (
-