{"id":8806,"date":"2026-01-25T08:43:23","date_gmt":"2026-01-25T07:43:23","guid":{"rendered":"https:\/\/innovacore.group\/?post_type=portfolio&p=8806"},"modified":"2026-03-17T15:52:57","modified_gmt":"2026-03-17T13:52:57","slug":"contribly","status":"publish","type":"portfolio","link":"https:\/\/innovacore.group\/zh-hans\/portfolio\/contribly\/","title":{"rendered":"Contribly &#8211; \u63d0\u5347\u8bfb\u8005\u53c2\u4e0e\u5ea6"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Contribly is a SaaS platform born at The Guardian, designed to master Community Generated Content (CGC) at scale. It streamlines the collection, moderation, and instant publishing of user stories, photos, and videos. By turning passive readers into active contributors, Contribly saves editorial teams significant time while drastically boosting loyalty, time-on-page, and first-party data collection for publishers and brands.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7528\u4e8e\u5927\u89c4\u6a21\u6536\u96c6\u3001\u5ba1\u6838\u548c\u53d1\u5e03\u793e\u533a\u5185\u5bb9\u7684SaaS\u5e73\u53f0\u3002<\/p>\n","protected":false},"featured_media":2369,"parent":0,"template":"","meta":{"inline_featured_image":false,"company_name":"Contribly","summary":"\u7528\u4e8e\u5927\u89c4\u6a21\u6536\u96c6\u3001\u5ba1\u6838\u548c\u53d1\u5e03\u793e\u533a\u5185\u5bb9\u7684SaaS\u5e73\u53f0\u3002","mission":"<p>\u5c06\u89c2\u4f17\u53c2\u4e0e\u8f6c\u5316\u4e3a\u6218\u7565\u6027\u5546\u4e1a\u8d44\u4ea7\u3002Contribly \u7684\u4f7f\u547d\u662f\u901a\u8fc7\u8ba9\u8bfb\u8005\u53c2\u4e0e\u6545\u4e8b\u53d8\u5f97\u8f7b\u800c\u6613\u4e3e\uff0c\u5e2e\u52a9\u51fa\u7248\u5546\u5efa\u7acb\u6df1\u539a\u7684\u4fe1\u4efb\u4e0e\u76f8\u5173\u6027\uff0c\u5c06\u53c2\u4e0e\u5ea6\u8f6c\u5316\u4e3a\u6709\u4ef7\u503c\u7684\u7b2c\u4e00\u65b9\u6570\u636e\u548c\u8ba2\u9605\u589e\u957f\u3002<\/p>\n","impact":"<p>Contribly \u6b63\u5728\u901a\u8fc7\u5c06\u4f20\u64ad\u5f0f\u5e7f\u64ad\u8f6c\u5411\u53cc\u5411\u5bf9\u8bdd\u6765\u91cd\u65b0\u5b9a\u4e49\u51fa\u7248\u673a\u6784\u4e0e\u53d7\u4f17\u7684\u5173\u7cfb\u3002\u5b83\u4e3a\u65b0\u95fb\u7f16\u8f91\u5ba4\u63d0\u4f9b\u4e00\u79cd\u201c\u4ef7\u503c\u4ea4\u6362\u201d\u6a21\u578b\uff0c\u80fd\u591f\u4ea7\u751f\u5bf9\u7b97\u6cd5\u65e0\u5173\u7684\u6d41\u91cf\u4e0e\u9ad8\u4ef7\u503c\u6570\u636e\uff0c\u8fd9\u5bf9\u4e8e\u5728\u4f9d\u8d56\u793e\u4ea4\u5e73\u53f0\u7684\u60c5\u51b5\u4e0b\u4e3a\u5a92\u4f53\u5546\u4e1a\u6a21\u5f0f\u5b9e\u73b0\u672a\u6765\u97e7\u6027\u81f3\u5173\u91cd\u8981\u3002<\/p>\n","company_logo":"https:\/\/innovacore.group\/wp-content\/uploads\/contribly_logo-innovacore-optimized.jpg","website_url":"https:\/\/www.contribly.com\/","linkedin_url":"https:\/\/www.linkedin.com\/company\/contribly\/","location":"Northwich, UK","founded_year":"","key_numbers":{"item-0":{"metric_label":"\u9875\u9762\u505c\u7559\u65f6\u95f4","metric_value":"3-10x"},"item-1":{"metric_label":"\u793e\u4ea4\u4e92\u52a8","metric_value":"3x"},"item-2":{"metric_label":"App \u4e0b\u8f7d\u63d0\u5347","metric_value":"44%"}},"hiring_status":"\u4fdd\u5bc6\u9636\u6bb5","sector":"\u8f6f\u4ef6\u5373\u670d\u52a1","company_type":"\u521d\u521b\u516c\u53f8","audience":["\u4f01\u4e1a\u5bf9\u4f01\u4e1a"],"geo_scope":["\u5168\u7403"],"business_model":["SaaS"],"funding_stage":"\u8fdb\u884c\u4e2d","partnership_type":"\u5347\u7ea7","logo_animation":"<div id=\"contribly-particle-root\">\r\n    <canvas id=\"contriblyCanvas\"><\/canvas>\r\n<\/div>\r\n\r\n<style>\r\n    #contribly-particle-root {\r\n        width: 100%;\r\n        height: 300px;\r\n        display: flex;\r\n        justify-content: center;\r\n        align-items: center;\r\n        background: transparent;\r\n        overflow: hidden;\r\n        cursor: crosshair;\r\n    }\r\n<\/style>\r\n\r\n<script>\r\n(function() {\r\n    const canvas = document.getElementById('contriblyCanvas');\r\n    const ctx = canvas.getContext('2d', { willReadFrequently: true });\r\n    const root = document.getElementById('contribly-particle-root');\r\n    \r\n    let width, height;\r\n    let particles = [];\r\n    let mouse = { x: -1000, y: -1000 };\r\n    const particleColor = '#f5f5f5'; \/\/ Gris clair demand\u00e9\r\n    let time = 0;\r\n\r\n    function init() {\r\n        width = root.offsetWidth;\r\n        height = 300;\r\n        \r\n        const dpr = window.devicePixelRatio || 1;\r\n        canvas.width = width * dpr;\r\n        canvas.height = height * dpr;\r\n        canvas.style.width = width + 'px';\r\n        canvas.style.height = height + 'px';\r\n        ctx.scale(dpr, dpr);\r\n\r\n        createLogoParticles();\r\n    }\r\n\r\n    function createLogoParticles() {\r\n        particles = [];\r\n        const cx = width \/ 2;\r\n        const cy = height \/ 2;\r\n        const isMobile = width < 600;\r\n\r\n        \/\/ --- 1. CONFIGURATION DU DESSIN ---\r\n        ctx.fillStyle = 'white';\r\n        ctx.strokeStyle = 'white';\r\n\r\n        \/\/ Dimensions relatives\r\n        \/\/ On augmente un peu la taille de l'ic\u00f4ne pour bien voir les d\u00e9tails\r\n        const iconSize = isMobile ? 60 : 100; \r\n        const fontSize = isMobile ? 35 : 60;\r\n        const gap = isMobile ? 15 : 30;\r\n\r\n        \/\/ Typo\r\n        ctx.font = `bold ${fontSize}px \"Poppins\", \"Montserrat\", Arial, sans-serif`;\r\n        const textMetrics = ctx.measureText('Contribly');\r\n        const textWidth = textMetrics.width;\r\n\r\n        \/\/ Centrage\r\n        const totalWidth = iconSize + gap + textWidth;\r\n        const startX = cx - (totalWidth \/ 2);\r\n        const centerY = cy;\r\n\r\n        \/\/ --- 2. DESSIN DE L'IC\u00d4NE (Complexe et fid\u00e8le) ---\r\n        const ix = startX;\r\n        const iy = centerY - (iconSize \/ 2);\r\n        const centerIx = ix + iconSize \/ 2;\r\n        const centerIy = iy + iconSize \/ 2;\r\n\r\n        \/\/ A. Le cadre carr\u00e9 (fin)\r\n        ctx.lineWidth = iconSize * 0.03;\r\n        ctx.strokeRect(ix, iy, iconSize, iconSize);\r\n\r\n        \/\/ B. Le Point Central (Le plus gros)\r\n        const centerDotRad = iconSize * 0.12;\r\n        ctx.beginPath();\r\n        ctx.arc(centerIx, centerIy, centerDotRad, 0, Math.PI * 2);\r\n        ctx.fill();\r\n\r\n        \/\/ C. Les Points P\u00e9riph\u00e9riques (Tailles et positions vari\u00e9es)\r\n        const networkRad = iconSize * 0.36; \/\/ Distance au centre\r\n        const bigRad = iconSize * 0.075;   \/\/ Rayon des \"gros\" points p\u00e9riph\u00e9riques\r\n        const smallRad = iconSize * 0.045; \/\/ Rayon des \"petits\" points\r\n\r\n        \/\/ D\u00e9finition manuelle des 6 points pour respecter le logo :\r\n        \/\/ Angles approximatifs en radians et taille associ\u00e9e.\r\n        const pointsDef = [\r\n            { angle: -0.4, size: smallRad }, \/\/ Haut-Droite (petit)\r\n            { angle: 0.3,  size: smallRad }, \/\/ Droite (petit)\r\n            { angle: 1.2,  size: bigRad },   \/\/ Bas-Droite (gros)\r\n            { angle: 2.6,  size: bigRad },   \/\/ Bas-Gauche (gros)\r\n            { angle: 3.5,  size: smallRad }, \/\/ Gauche (petit)\r\n            { angle: 4.5,  size: bigRad }    \/\/ Haut-Gauche (gros)\r\n        ];\r\n\r\n        ctx.lineWidth = iconSize * 0.025; \/\/ Lignes de connexion fines\r\n\r\n        pointsDef.forEach(pt => {\r\n            const px = centerIx + Math.cos(pt.angle) * networkRad;\r\n            const py = centerIy + Math.sin(pt.angle) * networkRad;\r\n\r\n            \/\/ 1. La ligne de connexion\r\n            ctx.beginPath();\r\n            ctx.moveTo(centerIx, centerIy);\r\n            ctx.lineTo(px, py);\r\n            ctx.stroke();\r\n\r\n            \/\/ 2. Le point\r\n            ctx.beginPath();\r\n            ctx.arc(px, py, pt.size, 0, Math.PI * 2);\r\n            ctx.fill();\r\n        });\r\n\r\n\r\n        \/\/ --- 3. DESSIN DU TEXTE ---\r\n        const textX = startX + iconSize + gap;\r\n        ctx.textAlign = 'left';\r\n        ctx.textBaseline = 'middle';\r\n        ctx.fillText('Contribly', textX, centerY);\r\n\r\n\r\n        \/\/ --- 4. SCAN DES PIXELS (Densit\u00e9 \u00e9lev\u00e9e pour le d\u00e9tail) ---\r\n        const density = 3;\r\n        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;\r\n        const dataWidth = canvas.width; \r\n\r\n        for (let y = 0; y < canvas.height; y += density) {\r\n            for (let x = 0; x < canvas.width; x += density) {\r\n                if (imageData[(y * dataWidth + x) * 4 + 3] > 128) {\r\n                    const dpr = window.devicePixelRatio || 1;\r\n                    particles.push({\r\n                        x: x \/ dpr,\r\n                        y: y \/ dpr,\r\n                        originX: x \/ dpr,\r\n                        originY: y \/ dpr,\r\n                        vx: 0, \r\n                        vy: 0,\r\n                        \/\/ Taille de particule l\u00e9g\u00e8rement variable pour le c\u00f4t\u00e9 \"soft\"\r\n                        size: Math.random() * 1.2 + 0.8, \r\n                    });\r\n                }\r\n            }\r\n        }\r\n        \r\n        ctx.clearRect(0, 0, width, height);\r\n    }\r\n\r\n    function draw() {\r\n        ctx.clearRect(0, 0, width, height);\r\n        \r\n        \/\/ --- PHYSIQUE \"SOFT\" ---\r\n        time += 0.02; \/\/ Vitesse d'ondulation lente\r\n\r\n        ctx.fillStyle = particleColor;\r\n        \r\n        particles.forEach(p => {\r\n            \/\/ 1. Respiration lente et ample\r\n            const waveX = Math.sin(time * 0.5 + p.y * 0.03) * 3;\r\n            const waveY = Math.cos(time * 0.4 + p.x * 0.03) * 3;\r\n\r\n            \/\/ 2. Interaction Souris douce\r\n            const dx = mouse.x - p.x;\r\n            const dy = mouse.y - p.y;\r\n            const dist = Math.sqrt(dx*dx + dy*dy);\r\n            const radius = 100;\r\n\r\n            let repelX = 0;\r\n            let repelY = 0;\r\n\r\n            if (dist < radius) {\r\n                const force = (radius - dist) \/ radius;\r\n                const angle = Math.atan2(dy, dx);\r\n                \/\/ Force mod\u00e9r\u00e9e (10) pour une r\u00e9pulsion visible mais pas violente\r\n                repelX = -Math.cos(angle) * force * 10;\r\n                repelY = -Math.sin(angle) * force * 10;\r\n            }\r\n\r\n            const targetX = p.originX + waveX;\r\n            const targetY = p.originY + waveY;\r\n\r\n            \/\/ 3. Physique fluide (Retour \u00e9lastique mou et forte friction)\r\n            const ax = (targetX - p.x) * 0.02; \/\/ Retour tr\u00e8s souple\r\n            const ay = (targetY - p.y) * 0.02;\r\n\r\n            p.vx += ax;\r\n            p.vy += ay;\r\n            p.vx += repelX * 0.2; \/\/ Application douce de la force souris\r\n            p.vy += repelY * 0.2;\r\n            \r\n            \/\/ Friction \u00e9lev\u00e9e pour l'effet \"flottant dans l'eau\"\r\n            p.vx *= 0.92; \r\n            p.vy *= 0.92;\r\n\r\n            p.x += p.vx;\r\n            p.y += p.vy;\r\n\r\n            ctx.beginPath();\r\n            ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);\r\n            ctx.fill();\r\n        });\r\n\r\n        requestAnimationFrame(draw);\r\n    }\r\n\r\n    const updateMouse = (e) => {\r\n        const r = canvas.getBoundingClientRect();\r\n        const cx = e.touches ? e.touches[0].clientX : e.clientX;\r\n        const cy = e.touches ? e.touches[0].clientY : e.clientY;\r\n        mouse.x = cx - r.left;\r\n        mouse.y = cy - r.top;\r\n    };\r\n\r\n    window.addEventListener('resize', init);\r\n    canvas.addEventListener('mousemove', updateMouse);\r\n    canvas.addEventListener('touchmove', updateMouse, {passive: true});\r\n    canvas.addEventListener('mouseleave', () => { mouse.x = -1000; mouse.y = -1000; });\r\n    canvas.addEventListener('touchend', () => { mouse.x = -1000; mouse.y = -1000; });\r\n\r\n    setTimeout(init, 100);\r\n    draw();\r\n})();\r\n<\/script>"},"pt":[],"pipeline":[],"class_list":["post-8806","portfolio","type-portfolio","status-publish","has-post-thumbnail","hentry"],"_links":{"self":[{"href":"https:\/\/innovacore.group\/zh-hans\/wp-json\/wp\/v2\/portfolio\/8806","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/innovacore.group\/zh-hans\/wp-json\/wp\/v2\/portfolio"}],"about":[{"href":"https:\/\/innovacore.group\/zh-hans\/wp-json\/wp\/v2\/types\/portfolio"}],"version-history":[{"count":1,"href":"https:\/\/innovacore.group\/zh-hans\/wp-json\/wp\/v2\/portfolio\/8806\/revisions"}],"predecessor-version":[{"id":8807,"href":"https:\/\/innovacore.group\/zh-hans\/wp-json\/wp\/v2\/portfolio\/8806\/revisions\/8807"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/innovacore.group\/zh-hans\/wp-json\/wp\/v2\/media\/2369"}],"wp:attachment":[{"href":"https:\/\/innovacore.group\/zh-hans\/wp-json\/wp\/v2\/media?parent=8806"}],"wp:term":[{"taxonomy":"pt","embeddable":true,"href":"https:\/\/innovacore.group\/zh-hans\/wp-json\/wp\/v2\/pt?post=8806"},{"taxonomy":"pipeline","embeddable":true,"href":"https:\/\/innovacore.group\/zh-hans\/wp-json\/wp\/v2\/pipeline?post=8806"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}